NEW: Subscribe to Hacking with Swift+ and accelerate your learning! >>

How ScrollView lets us work with scrolling data

Paul Hudson    @twostraws   

You’ve seen how List and Form let us create scrolling tables of data, but for times when we want to scroll arbitrary date – i.e., just some views we’ve created by hand – we need to turn to SwiftUI’s ScrollView.

Scroll views can scroll horizontally, vertically, or in both directions, and you can also control whether the system should show scroll indicators next to them – those are the little scroll bars that appear to give users a sense of how big the content is. When we place views inside scroll views, they automatically figure out the size of that content so users can scroll from one edge to the other.

As an example, we could create a scrolling list of 100 text views like this:

ScrollView(.vertical) {
    VStack(spacing: 10) {
        ForEach(0..<100) {
            Text("Item \($0)")
                .font(.title)
        }
    }
}

If you run that back in the simulator you’ll see that you can drag the scroll view around freely, and if you scroll to the bottom you’ll also see that ScrollView treats the safe area just like List and Form – their content goes under the home indicator, but they add some extra padding so the final views are fully visible.

You might also notice that it’s a bit annoying having to tap directly in the center – it’s more common to have the whole area scrollable. To get that behavior, we should make the VStack take up more space while leaving the default centre alignment intact, like this:

ScrollView(.vertical) {
    VStack(spacing: 10) {
        ForEach(0..<100) {
            Text("Item \($0)")
                .font(.title)
        }
    }
    .frame(maxWidth: .infinity)
}

Now you can tap and drag anywhere on the screen, which is much more user-friendly.

This all seems really straightforward, and it’s true that ScrollView is significantly easier than the older UIScrollView we had to use with UIKit. However, there’s an important catch that you need to be aware of: when we add views to a scroll view they get created immediately.

To demonstrate this, we can create a simple wrapper around a regular text view, like this:

struct CustomText: View {
    var text: String

    var body: some View {
        Text(text)
    }

    init(_ text: String) {
        print("Creating a new CustomText")
        self.text = text
    }
}

Now we can use that inside our ForEach:

ForEach(0..<100) {
    CustomText("Item \($0)")
        .font(.title)
}

The result will look identical, but now when you run the app you’ll see “Creating a new CustomText” printed a hundred times in Xcode’s log – SwiftUI won’t wait until you scroll down to see them, it will just create them immediately.

You can try the same experiment with a List, like this:

List {
    ForEach(0..<100) {
        CustomText("Item \($0)")
            .font(.title)
    }
}

When that code runs you’ll see it acts lazily: it creates instances of CustomText only when really needed.

Hacking with Swift is sponsored by Instabug

SPONSORED Are you tired of wasting time debugging your Swift app? Instabug’s SDK is here to help you minimize debugging time by providing you with complete device details, network logs, and reproduction steps with every bug report. All data is attached automatically, and it only takes a line of code to setup. Start your free trial now and get 3 months off exclusively for the Hacking with Swift Community.

Start your free trial!

Sponsor Hacking with Swift and reach the world's largest Swift community!

BUY OUR BOOKS
Buy Pro Swift Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift (Vapor Edition) Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Server-Side Swift (Kitura Edition) Buy Beyond Code

Was this page useful? Let us know!

Average rating: 4.5/5

Link copied to your pasteboard.