Chapters

Hide chapters

SwiftUI by Tutorials

Fifth Edition · iOS 16, macOS 13 · Swift 5.8 · Xcode 14.2

Before You Begin

Section 0: 4 chapters
Show chapters Hide chapters

21. Complex Interfaces
Written by Bill Morefield

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

SwiftUI represents an exciting new paradigm for UI design. However, it’s new, and it doesn’t provide all the same functionality found in UIKit, AppKit and other frameworks. The good news is that anything you can do using AppKit or UIKit, you can recreate in SwiftUI!

SwiftUI does provide the ability to build upon an existing framework and extend it to add missing features. This capability lets you replicate or extend functionality while also staying within the native framework.

In this chapter, you’ll also work through building a reusable view that can display other views in a grid. You’ll then look at integrating a UIKit view to implement functionality not available in SwiftUI.

Building Reusable Views

SwiftUI builds upon the idea of composing views from smaller views. Because of this, you often end up with blocks of views within views within views, as well as SwiftUI views that span screens of code. Splitting components into separate views makes your code cleaner. It also makes it easier to reuse the component in many places and multiple apps.

Open the starter project for this chapter. Build and run the app. Tap on the Flight Timeline button to bring up the empty timeline view. Right now, it shows a scrollable list of the flights. You’re going to build a timeline view, then change it to a more reusable view.

Simple flight list
Simple flight list

It’s useful to keep a new solution simple in development instead of trying to do everything at once. You will initially build the timeline specific to your view. First, you’ll work on the cards.

Open FlightCardView.swift inside the Timeline folder and add the following view above FlightCardView:

struct DepartureTimeView: View {
  var flight: FlightInformation

  var body: some View {
    VStack {
      if flight.direction == .arrival {
        Text(flight.otherAirport)
      }
      Text(
        shortTimeFormatter.string(
          from: flight.departureTime)
      )
    }
  }
}

This view displays the departure and arrival times for the flight with the airport’s name above the other end’s time.

Add the following code after the just added view:

struct ArrivalTimeView: View {
  var flight: FlightInformation

  var body: some View {
    VStack {
      if flight.direction == .departure {
        Text(flight.otherAirport)
      }
      Text(
        shortTimeFormatter.string(
          from: flight.arrivalTime
        )
      )
    }
  }
}

Now to use those new views. Inside FlightCardView, add the following code at the end of the VStack:

HStack(alignment: .bottom) {
  DepartureTimeView(flight: flight)
  Spacer()
  ArrivalTimeView(flight: flight)
}

Run the app, view the Flight Timeline and you’ll see your changes.

Simple flight cards
Simple flight cards

Showing Flight Progress

Next, you’ll add an indicator of the progress of a flight to the card. The status of a flight will usually be either before departure or after landing. In between, there’s a time where the flight will be a portion of the way between the airports.

Adding Inline Drawings

In this section you’ll add a view to show the flight progress. Add the following view after the ArrivalTimeView view struct:

Kmafang pyukgl cxiqjevl
Yfihizs rzokvs xrafpawx

Using a ViewBuilder

The timeline you’ve created always shows the same view. It would be much more useful to let the caller specify what to display for each item. That’s where the SwiftUI ViewBuilder comes in.

Qokacegi kuzn exjjotac caad
Xuvusafa nill obtvidif biux

Making the Timeline Generic

Generics allow you to write code without being specific about the type of data you’re using. You can write a function once and use it on any data type.

Gumesuy liyoripu
Hidaqin jiyaseba

Using Keypaths

A KeyPath lets you refer to a property on an object. That’s not the same as the contents of the property, as KeyPath represents the property itself. You use them quite often in SwiftUI. In fact, you’re already using them. In the last section you used a KeyPath in the following code:

Using the Timeline

First let’s give a nicer appearance to the cards. Open FlightCardView.swift and add the following at the end of the VStack:

Qexxcekuh cetivubi
Nitjrazen raqiburo

Integrating With Other Frameworks

SwiftUI continues to add new features, but it can’t do everything possible in UIKit or AppKit. That’s because many of the built-in frameworks do not have a corresponding component in SwiftUI. Other components, such as MapKit, does not offer all the features of the original framework. You also may have third-party controls that you already use in your app and need to continue integrating during the transition to SwiftUI. In this section, you’ll look at using your generic timeline with MapKit.

Zgathez nifseiy
Vdoxnax jiqpeem

Connecting Delegates, Data Sources and More

If you’re familiar with MKMap in iOS, you might wonder how you provide the delegate to add overlays to this MKMapView. If you try accessing data inside a SwiftUI struct directly from UIKit, your app will crash. Instead, you have to create a Coordinator object as an NSObject derived class.

Vecavoku funv cis
Wagekato yust moy

Key Points

  • You build views using Representable — derived protocols to integrate SwiftUI with other Apple frameworks.
  • There are two required methods in these protocols to create the view and do setup work.
  • A Controller class gives you a way to connect data in SwiftUI views with a view from previous frameworks. You can use this to manage delegates and related patterns.
  • You instantiate the Controller inside your SwiftUI view and place other framework code within the Controller class.
  • You can use a ViewBuilder to pass views into another view when doing iterations.
  • Generics let your views work without hard-coding specific types.
  • A KeyPath provides a way to reference a property on an object without invoking the property.

Where to Go From Here?

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now