Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2022 EssentialsSwift

WWDC22 · 13 min · Essentials / Swift

Meet Swift Async Algorithms

Discover the latest open source Swift package from Apple: Swift Async Algorithms. We’ll explore algorithms from this package that you can use with AsyncSequence, including zip, merge, and throttle. Follow along with us as we use these algorithms to build a great messaging app. We’ll also share best practices for combining multiple AsyncSequences and using the Swift Clock type to work with values over time. To get the most out of this session, we recommend watching "Meet AsyncSequence."

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 9 snippets

The messaging app swift · at 2:01 ↗
struct Account {
  var messages: AsyncStream<Message>
}  

actor AccountManager {
  var primaryAccount: Account
  var secondaryAccount: Account? 
}

protocol MessagePreview {
  func displayPreviews(_ manager: AccountManager) async
}
Zip swift · at 3:16 ↗
// upload attachments of videos and previews such that every video has a preview that are created concurrently so that neither blocks each other. 

for try await (vid, preview) in zip(videos, previews) {
  try await upload(vid, preview)
}
Merge swift · at 5:09 ↗
// Display previews of messages from either the primary or secondary account

for try await message in merge(primaryAccount.messages, secondaryAccount.messages) {
  displayPreview(message)
}
Suspending Clock swift · at 6:37 ↗
// Sleep until a given deadline

let clock = SuspendingClock()
var deadline = clock.now + .seconds(3)
try await clock.sleep(until: deadline)
Suspending Clock vs. Continuous Clock swift · at 6:56 ↗
let clock = SuspendingClock()
let elapsed = await clock.measure {
  await someLongRunningWork()
}
//Elapsed time reads 00:05.40

let clock = ContinuousClock()
let elapsed = await clock.measure {
  await someLongRunningWork()
}
//Elapsed time reads 00:19.54
Control searching messages swift · at 8:34 ↗
// Control searching messages

class SearchController {
  let searchResults = AsyncChannel<SearchResult>()

  func search<SearchValues: AsyncSequence>(_ searchValues: SearchValues) 
    where SearchValues.Element == String 
}
Debounce swift · at 9:16 ↗
let queries = searchValues
   .debounce(for: .milliseconds(300))

for await query in queries {
  let results = try await performSearch(query)
  await channel.send(results)
}
Chunked by swift · at 10:21 ↗
let batches = outboundMessages.chunked(
  by: .repeating(every: .milliseconds(500))
)

let encoder = JSONEncoder() 
for await batch in batches {
  let data = try encoder.encode(batch)
  try await postToServer(data) 
}
Conversions in initializers swift · at 11:22 ↗
// Create a message with awaiting attachments to be encoded
init<Attachments: AsyncSequence>(_ attachments: Attachments) async rethrows {
  self.attachments = try await Array(attachments)
}

Resources