Instruction

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

Using the Task Modifier

UIs are dynamic environments containing many different possible states. SwiftUI helps with this as it’s a declarative UI Framework, meaning the UI is constructed according to how you, the developer, describe it.

struct TripsListView: View {
  // 1
  @State fileprivate var tripsStore = TripsStore()
  @State private var tripCount = "Loading.."
  
  var body: some View {
    Text(tripCount)
    // 2
    List(tripsStore.trips) { trip in
      TripsListRowView(trip: trip)
    }
    //3
    .task {
      let trips = await tripsStore.fetchTrips().count()
      // 4
      tripCount = "You have \(trips) planned!"
    }
  }
}

Simplifying With AsyncImage

A common use case of apps is downloading images and displaying them. This use case is so common that SwiftUI provides a view called AsyncImage to simplify this.

struct TripsListRowView: View {
  // 1
  let trip: Trip
  
  var body: some View {
    //2
    AsyncImage(url: trip.imageUrl)
    // 3
    .frame(width: 200, height: 200)

    Text(trip.name)
  }
}
  AsyncImage(url: trip.imageUrl) { image in
      image.resizable()
  } placeholder: {
      YourCustomProgressView()
  }
  .frame(width: 200, height: 200)

Viewing Concurrency Performance Using Instruments

Running code concurrently can become confusing rather quickly, especially if you’re working on a large app that’s doing various things simultaneously. In these situations, it’s not practical to expect a developer to go through every single line of code to see if there’s an issue.

Swift Concurrency as an option in Instruments
Glozx Bezfaxpehfy og id ubriix ez Osgjdecovmh

Running Swift Concurrency Instruments
Weshejj Hnafr Wandawxadxm Avdvsamessw

Writing Asynchronous Tests

It’s good practice to verify that your asynchronous code works as expected by testing it. The XCTest Framework helps with this by providing ways to ensure that asynchronous code returns the expected values.

    // 1
func testDownloadTripDataWithConcurrency() async throws {
  // 2
  let expectedTrips = [Trip(imageUrl: "https://tripfinder.com/trip/20234/image", name: "Trip to Scotland"),
                        Trip(imageUrl: "https://tripfinder.com/trip/99234/image", name: "Trip to New York"),
                        Trip(imageUrl: "https://tripfinder.com/trip/63154/image", name: "Trip to Kenya")]
    
  // 3
  let fetchedTrips: [Trip] = try await tripsService.fetchTrips()
    
  // 4
  XCTAssertEqual(fetchedTrips, actualTrips, "Expected trips with correct values.")
}
@MainActor
func testDownloadTripDataWithConcurrency() async throws {

  let expectedTrips = [Trip(imageUrl: "https://tripfinder.com/trip/20234/image",
                            name: "Trip to Scotland"),
                        Trip(imageUrl: "https://tripfinder.com/trip/99234/image",
                            name: "Trip to New York"),
                        Trip(imageUrl: "https://tripfinder.com/trip/63154/image",
                            name: "Trip to Kenya")]

  let viewModel = TripsViewModel(tripsService: tripsService)
  try await viewModel.fetchTrips()

  XCTAssertEqual(viewModel.trips, expectedTrips, "ViewModel should have updated trips.")
}
See forum comments
Download course materials from Github
Previous: Introduction Next: Demo