Beginning Networking with URLSession

Sep 13 2022 · Swift 5.6, iOS 15, Xcode 13.4.1

Part 1: Introduction to URLSession & Concurrency

03. More Modern Concurrency

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. Introduction to Modern Concurrency Next episode: 04. Challenge: Run Code on the Main Thread

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.

Notes: 03. More Modern Concurrency

Concurrency - The Swift Programming Language

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

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

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

Unlock now

Continuing from the previous episode, let’s take a look at more of Swift’s modern concurrency features.

func findTitle(url: URL) async throws -> String? {
  for try await line in url.lines {
    if line.contains("<title>") {
      return line.trimmingCharacters(in: .whitespaces)
    }
  }
    
  return nil
}
Task {
  if let title = try await findTitle(url: URL(string: "https://www.raywenderlich.com")!) {
    print(title)
  }
}
extension Domains {
  static var domains: [Domain] {
    get async throws {
      try await fetchDomains()
    }
  }
}
Task {
  dump(try await Domains.domains)
}
extension Domains {
  enum Error: Swift.Error { case outOfRange }
    
  static subscript(_ index: Int) -> String {
    get async throws {
      let domains = try await Self.domains
      guard domains.indices.contains(index) else {
        throw Error.outOfRange
      }
      return domains[index].attributes.name
    }
  }
}

Task {
  dump(try await Domains[4])
}
public actor Playlist {
public func move(song: String, from playlist: Playlist) async
public func move(song: String, to playlist: Playlist) async 
public func move(song: String, from playlist: Playlist) async {
  await playlist.remove(song: song)
  add(song: song)
}
public func move(song: String, to playlist: Playlist) async {
   await playlist.add(song: song)
   remove(song: song)
}
let favoritesPlaylist = Playlist(title: "Favorite songs",
                                author: "Felipe",
                                songs: ["In And Out Of Love"])
let partyPlaylist = Playlist(title: "Party songs",
                            author: "Ray",
                            songs: ["Hello"])
Task {
 await favoritesPlaylist.move(song: "Hello", from: partyPlaylist)
 await favoritesPlaylist.move(song: "In And Out Of Love", to: partyPlaylist)
 await print(favoritesPlaylist.songs)
 await print(partyPlaylist.songs)
}
let url = URL(string: "https://api.raywenderlich.com/api/domains")!
let session = URLSession.shared.dataTask(with: url) { data, _, _ in
  guard let data = data,
        let domain = try? JSONDecoder().decode(Domains.self, from: data).data.first
  else {
    print("Request failed")
        
    return
  }
    
  Task {
    await MainActor.run {
      print(domain)
      print(Thread.isMainThread)
    }
  }
}

session.resume()
Task { @MainActor in
  print(domain)
  print(Thread.isMainThread)
}
extension Domains {
  func domainNames() -> [String] {
    print("Getting domain names in main thread? \(Thread.isMainThread)")
        
    return data.map { $0.attributes.name }
  }
}

let session2 = URLSession.shared.dataTask(with: url) { data, _, _ in
  guard let data = data,
        let domains = try? JSONDecoder().decode(Domains.self, from: data)
  else {
    print("Request failed")
        
    return
  }

  print(domains.domainNames())
}

session2.resume()
@MainActor func domainNames() -> [String] {
Task {
  await print(domains.domainNames())
}