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 expanding lists (iOS 14+)

Expanding lists can be used to display hierarchical structures within a list. Each list item can be expanded to view its contents. The expanding ability is achieved by creating a struct that holds some information and an optional array of items of the same type as the struct itself. Let's examine how expanding lists work by creating an app that displays the contents of a backpack.

Getting ready

Create a new SwiftUI app and name it UsingExpandingLists.

How to do it…

We start by creating the Backpack struct that describes the properties of the data we want to display. We'll then create a number of Backpack constants and display the hierarchical information using a List view containing a children property.

The steps are as follows:

  1. At the bottom of the ContentView.swift file, define a Backpack struct that has an id, name, icon, and content property. The content property's type should be an optional array of Backpack structs:
    struct Backpack: Identifiable {
        let id = UUID()
        let name: String
        let icon: String
        var content: [Backpack]?
    }
  2. Below the Backpack struct declaration, create three variables: two currency types and an array of currencies:
    let dollar = Backpack(name: "Dollar", icon: "dollarsign.   circle")
    let yen = Backpack(name: "Yen",icon: "yensign.circle")
    let currencies = Backpack(name: "Currencies", icon:    "coloncurrencysign.circle", content: [dollar, yen])
  3. Create a pencil, hammer, paperclip, and glass constant:
    let pencil = Backpack(name: "Pencil",icon: "pencil.  circle")
    let hammer = Backpack(name: "Hammer",icon: "hammer")
    let paperClip = Backpack(name: "Paperclip",icon:   "paperclip")
    let glass = Backpack(name: "Magnifying glass",   icon: "magnifyingglass")
  4. Create a bin Backpack constant that contains paperclip and glass, as well as a tool constant that holds pencil, hammer, and bin:
    let bin  = Backpack(name: "Bin", icon: "arrow.up.bin",  content: [paperClip, glass])
    let tools = Backpack(name: "Tools", icon: "folder",   content: [pencil, hammer,bin])
  5. Going back to the ContentView struct, add an instance property; items, which contains an array of two items, the currencies and tools constants defined earlier:
    struct ContentView: View {
        let items = [currencies,tools]
        …
    }
  6. Within the body variable, replace the Text view with a List view that displays the content of the items array:
        var body: some View {
            List(items, children: \.content){ row in
                Image(systemName: row.icon)
                Text(row.name)
            }
        }

    The resulting Xcode live preview should look as follows when expanded:

Figure 2.16 – UsingExpandingLists

Figure 2.16 – Using expanding lists

Run the Xcode live preview and click on the arrows to expand and collapse the views.

How it works…

We start by creating a struct of the proper format for expanding lists. Expanding lists require one of the struct properties to be an optional array of the same type as the struct itself. Our Backpack content property holds an optional array of Backpack items:

struct Backpack: Identifiable {
    let id = UUID()
    let name: String
    let icon: String
    var content: [Backpack]?
}

The UUID() function generates a random identifier and stores it in the id property. We can manually provide the name, icon, and content variables for the items we add to the backpack.

We create our first hierarchical structure by creating the Dollar and Yen variables:

let dollar = Backpack(name: "Dollar", icon: "dollarsign.  circle")
let yen = Backpack(name: "Yen",icon: "yensign.circle")

Observe that no content property has been provided for both variables. This is possible because the content is an optional parameter.

We then create a currencies constant that that has name and icon. The Dollar and Yen variables created earlier are added to its content array.

We use a similar composition to add elements to our tool constant.

After setting up the data we want to display, we create an item property in our ContentView struct that holds an array of Backpack constants created earlier:

let items = [currencies,tools]

Finally, we replace the Text view in the ContentView body with a List view that iterates over the items. The list is made expandable by adding the children parameter, which expects an array of the same time as the struct passed to the List view.

There's more…

The tree structure used for expandable lists can also be generated on a single line, as follows:

let tools = Backpack(name: "Tools", icon: "folder", content:
   [Backpack(name: "Pencil",icon: "pencil.circle"),
    Backpack(name: "Hammer",icon: "hammer"),
    Backpack(name: "Bin", icon: "arrow.up.bin", content:
        [Backpack(name: "Paperclip",icon: "paperclip"),
         Backpack(name: "Magnifying glass", icon:           "magnifyingglass")
           ])
       ])

The SwiftUI List view provides out-of-the-box support for OutlineGroup in iOS 14. OutlineGroup computes views and disclosure groups on demand from an underlying collection.

See also

Refer to the WWDC20 video on stacks, grids, and outlines at https://developer.apple.com/videos/play/wwdc2020/10031/.

Refer to the Apple documentation on OutlineGroup at https://developer.apple.com/documentation/swiftui/outlinegroup.