Swift - toant-dev/toandev.github.io GitHub Wiki

Swift 5.5

https://www.hackingwithswift.com/articles/233/whats-new-in-swift-5-5

async/await

func listPhotos(inGallery name: String) async -> [String] {
    await Task.sleep(2 * 1_000_000_000)  // Two seconds
    return ["IMG001", "IMG99", "IMG0404"]
}
let handle = FileHandle.standardInput
for try await line in handle.bytes.lines {
    print(line)
}
let firstPhoto = await downloadPhoto(named: photoNames[0])
let secondPhoto = await downloadPhoto(named: photoNames[1])
let thirdPhoto = await downloadPhoto(named: photoNames[2])

let photos = [firstPhoto, secondPhoto, thirdPhoto]
show(photos)

// ----------- concurrent vs paralle --------------------

async let firstPhoto = downloadPhoto(named: photoNames[0])
async let secondPhoto = downloadPhoto(named: photoNames[1])
async let thirdPhoto = downloadPhoto(named: photoNames[2])

let photos = await [firstPhoto, secondPhoto, thirdPhoto]
show(photos)

Task and TaskGroup

    let task = Task { () -> String in
        print("Starting")
        await Task.sleep(1_000_000_000)
        try Task.checkCancellation()
        return "Done"
    }

    // The task has started, but we'll cancel it while it sleeps
    task.cancel()

await withTaskGroup(of: Data.self) { taskGroup in
    let photoNames = await listPhotos(inGallery: "Summer Vacation")
    for name in photoNames {
        taskGroup.async { await downloadPhoto(named: name) }
    }
}

Actors

SE-0306 introduces actors, which are conceptually similar to classes that are safe to use in concurrent environments. This is possible because Swift ensures that mutable state inside your actor is only ever accessed by a single thread at any given time, which helps eliminate a variety of serious bugs right at the compiler level.

Actors handle their synchronization internally

actor SafeCollector {
    var deck: Set<String>

    init(deck: Set<String>) {
        self.deck = deck
    }

    func send(card selected: String, to person: SafeCollector) async -> Bool {
        guard deck.contains(selected) else { return false }

        deck.remove(selected)
        await person.transfer(card: selected)
        return true
    }

    func transfer(card: String) {
        deck.insert(card)
    }
}

@MainActor

class NewDataController {
    @MainActor func save() {
        print("Saving data…")
    }
}

With @MainActor we can guarantee that save() is always called on the main thread as if we specifically ran it using DispatchQueue.main. No need to check Thread.isMainThread

Sendable and @Sendable closures

SE-0302 adds support for “sendable” data, which is data that can safely be transferred to another thread. This is accomplished through a new Sendable protocol, and an @Sendable attribute for functions.

Many things are inherently safe to send across threads:

  • All of Swift’s core value types, including Bool, Int, String, and similar.
  • Optionals, where the wrapped data is a value type.
  • Standard library collections that contain value types, such as Array or Dictionary<Int, String>.
  • Tuples where the elements are all value types.
  • Metatypes, such as String.self.

lazy now works in local contexts

func lazyTest() {
    print("Before lazy")
    lazy var greeting = printGreeting(to: "Paul")
    print("After lazy")
    print(greeting)
}

Allow interchangeable use of CGFloat and Double types

let first: CGFloat = 42
let second: Double = 19
let result = first + second
print(result)

Codable synthesis for enums with associated values

enum Weather: Codable {
    case sun
    case wind(speed: Int)
    case rain(amount: Int, chance: Int)
}

Extend property wrappers to function and closure parameters

@propertyWrapper
struct Clamped<T: Comparable> {
    let wrappedValue: T

    init(wrappedValue: T, range: ClosedRange<T>) {
        self.wrappedValue = min(max(wrappedValue, range.lowerBound), range.upperBound)
    }
}

func setScore2(@Clamped(range: 0...100) to score: Int) {
    print("Setting score to \(score)")
}

setScore2(to: 50) // OK = 50
setScore2(to: -50) // OK = 0
setScore2(to: 500) // OK = 100
⚠️ **GitHub.com Fallback** ⚠️