Modern Concurrency: Getting Started

Oct 18 2022 · Swift 5.5, iOS 15, Xcode 13.4

Part 1: Asynchronous Code

03. Your First Asynchronous App

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 02. Getting Started Next episode: 04. Asynchronous Sequences

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

Run the course server

Most of the projects in this course interact with a server. It’s included in the course materials.

LittleJohn app

For the rest of this part of the course, you’ll work on this simple ticker app. In this episode, you’ll fetch a list of stock symbols from the course server.

Fetch stock symbols

In your browser, reload the server page to check it’s still running.

Non-async code in starter

In LittleJohnModel, locate availableSymbols():

func availableSymbols() async throws -> [String] {
  guard let url = URL(string: "http://localhost:8080/littlejohn/symbols")
  else {
    throw "The URL could not be created."
  }
  return []
}

Add async call: async throws / try await

The async keyword indicates this function contains a suspension point, which you’ll add now… just before the return statement:

let (data, response) = try await URLSession.shared.data(from: url)
🟥return []

Handle data, response

Next, you need to verify the server response and return the fetched data. Replace the dummy return line with this code:

let (data, response) = try await URLSession.shared.data(from: url)
🟩
guard (response as? HTTPURLResponse)?.statusCode == 200 else {
  throw "The server responded with an error."
}
return try JSONDecoder().decode([String].self, from: data)

Call async method from SwiftUI view

Before you run the app, you need to update the SwiftUI view to use your new async method.

.padding(.horizontal)
// TODO: Call model.availableSymbols()
🟩
.onAppear {
  symbols = try await model.availableSymbols() 
}
Invalid conversion from 'async' function of type '() async throws -> ()' to synchronous function type '() -> Void'
.🟩task🟥 {
  symbols = try await model.availableSymbols()
}
.task {
  do {
    symbols = try await model.availableSymbols()
  } catch  {

  }
}
.task {
  🟩guard symbols.isEmpty else { return }🟥
  do {
} catch  {
  🟩lastErrorMessage = error.localizedDescription🟥
}

Test error handling

How about testing whether SymbolListView catches an error thrown by availableSymbols()?