Book Image

SwiftUI Cookbook

By : Giordano Scalzo, Edgar Nzokwe
Book Image

SwiftUI Cookbook

By: Giordano Scalzo, Edgar Nzokwe

Overview of this book

SwiftUI is an innovative and simple way to build beautiful user interfaces (UIs) for all Apple platforms, right from iOS and macOS through to watchOS and tvOS, using the Swift programming language. In this recipe-based book, you’ll work with SwiftUI and explore a range of essential techniques and concepts that will help you through the development process. The recipes cover the foundations of SwiftUI as well as the new SwiftUI 2.0 features introduced in iOS 14. Other recipes will help you to make some of the new SwiftUI 2.0 components backward-compatible with iOS 13, such as the Map View or the Sign in with Apple View. The cookbook begins by explaining how to use basic SwiftUI components. Then, you’ll learn the core concepts of UI development such as Views, Controls, Lists, and ScrollViews using practical implementation in Swift. By learning drawings, built-in shapes, and adding animations and transitions, you’ll discover how to add useful features to the SwiftUI. When you’re ready, you’ll understand how to integrate SwiftUI with exciting new components in the Apple development ecosystem, such as Combine for managing events and Core Data for managing app data. Finally, you’ll write iOS, macOS, and watchOS apps while sharing the same SwiftUI codebase. By the end of this SwiftUI book, you'll have discovered a range of simple, direct solutions to common problems found in building SwiftUI apps.
Table of Contents (15 chapters)

Using LazyHStack and LazyVStack (iOS 14+)

SwiftUI 2.0 introduced the LazyHStack and LazyVStack components. These components are used in a similar way to regular HStack and VStack components but offer the advantage of lazy loading. Lazy components are loaded just before the item becomes visible on the device's screen during a device scroll, therefore reducing latency.

We will create an app that uses LazyHStack and LazyVStack and observe how it works.

Getting ready

Let's create a new SwiftUI app called LazyStacks:

  1. Open Xcode and click Create New Project.
  2. In the Choose template window, select iOS and then App.
  3. Click Next.
  4. Enter LazyStacks in the Product Name field and select SwiftUI App from the Life Cycle field.
  5. Click Next and select a location on your computer where the project should be stored.

How to do it…

We will implement a LazyHStack and LazyVStack view within a single SwiftUI view file by embedding both in a VStack component. The steps are as follows:

  1. Click on the ContentView.swift file to view its content in Xcode's editor pane.
  2. Let's create a ListRow SwiftUI view that will have two properties: an ID and a type. ListRow should also print a statement showing what item is currently being initialized:
    struct ListRow: View {
        let id: Int
        let type: String
        init(id: Int, type: String){
            print("Loading \(type) item \(id)")
            self.id = id
            self.type = type
        }
        var body: some View {
            Text("\(type) \(id)").padding()
        }
    }
  3. Replace the initial Text view with VStack:
    VStack {
    }
  4. Add a horizontal scroll view inside the VStack component and use a .frame() modifier to limit the view's height:
    ScrollView(.horizontal){
    }.frame(height: 100, alignment: .center)
  5. Add LazyHStack inside the scroll view with a ForEach view that iterates through the numbers 110000 and displays them using our ListRow view:
    LazyHStack {
         ForEach(1...10000, id:\.self){ item in
           ListRow(id: item, type: "Horizontal")
               }
                    }
  6. Add a second vertical scroll view to VStack with a LazyVStack struct that loops through numbers 110000:
    ScrollView {
      LazyVStack {
        ForEach(1...10000, id:\.self){ item in
          ListRow(id: item, type: "Vertical")
                 }
            }
        }
  7. Now, let's observe lazy loading in action. If the Xcode debug area is not visible, click on View | Debug Area | Show Debug Area:
    Figure 2.10 – Show Debug Area

    Figure 2.10 – Show Debug Area

  8. Select a simulator to use for running the app. The app should look as follows:
    Figure 2.11 – Selecting the simulator from Xcode

    Figure 2.11 – Selecting the simulator from Xcode

  9. Click the play button to run the code in the simulator:
    Figure 2.12 – The LazyStacks app running on the simulator

    Figure 2.12 – The LazyStacks app running on the simulator

  10. Scroll through the items in LazyHStack (located at the top). Observe how the print statements appear in the debug area just before an item is displayed on the screen. Each item is initialized just before it is displayed.
  11. Scroll through the items in LazyVStack. Observe how the print statements appear in the debug area just before an item is displayed.

How it works…

We started this recipe by creating the ListRow view because we wanted to clearly demonstrate the advantage of lazy loading over the regular method where all items get loaded at once. The ListRow view has two properties: an ID and a string. We add a print statement to the init() function so that we can observe when each item gets initialized:

    init(id: Int, type: String){
        print("Loading \(type) item \(id)")
        self.id = id
        self.type = type
    }

The ListRow view body presents a Text view with the ID and type parameters passed to it.

Moving up to the ContentView struct, we replace the initial Text view in the body variable with a VStack component. This allows us to implement both LazyHStack and LazyVStack within the same SwiftUI view.

We implement LazyHStack by first wrapping it in a scroll view, then using a ForEach struct to iterate over the range of values we want to display. For each of those values, a new ListRow view is initialized just before it becomes visible when the user scrolls down:

ScrollView {
  LazyVStack {
   ForEach(1...10000, id:\.self){ item in
    ListRow(id: item, type: "Vertical")
             }
          }
       }

Run the app using a device emulator to view the print statements before each item is initialized. Nothing will be printed if the app is run in live preview mode on Xcode.

There's more…

Try implementing the preceding app using a regular HStack or VStack component and observe the performance difference. The app will be significantly slower since all the rows are initialized at once.