[WWDC21] What`s new in Swift (Swift 5.5)

4 minute read

Diversity

Update on Swift Package

Package Collections in Xcode

swift1

  • simple JSON files you can publish anywhere
  • curated lists of packages for different use cases

Apple Packages

  • Collections Package, Algorithms Package, System Package, Numeric Package, ArgumentParser Package, …

The Collections Package

Deque

  • an Array
import Collections

var colors: Deque = ["red", "yellow", "blue"]

colors.prepend["green"]
colors.append["orange"]
// colors is now ["green", "red", "yellow", "blue", "orange"]

colors.popFirst()
colors.popLast()
// colors is now ["red", "yellow", "blue"]

OrderedSet

  • powerful hybrid of an Array and a Set
import Collections

var buildingMaterials: OrderdSet = ["straw", "sticks", "bricks"]

for i in 0 ..<buildingMaterials.count {
    print("#\(i) \(buildingMaterials[i]")
}

buildingMaterials.append("straw") // (inserted: false, index: 0)

OrderedDictionary

  • a useful alternative to Dictionary when order is important
import Collections

var responses: OrderedDictionary = [200: "OK", 403: "Forbidden", 404: "Not Found"]

var (cod, phrase) in responses {
    print("\(code) (\(phrase))")
}

The Algorithms Package

import Algorithms

let testAccounts = [ ... ]

for testGroup in testAccounts.uniquePermutations(ofCount: 0...) {
    try validate(testGroup)
}

let randomGroup = testAccounts.randomSample(count: 5)

The System Package

import System

var path: FilePath = "/tmp/WWDC2021.txt"
print(path.lastComponent)   // "WWDC2021.txt"
print(path.extension)       // "txt"

The Numeric Package

import Numerics

let x: Float16 = 1.5
let y = Float16.exp(x)

let z = Complex(0, Float16.pi)
let w = Complex.exp(z)

The ArgumentParser Package

  • github.com/apple/swift-argument-parser
  • to generate code-completion scripts for the Fish shell
  • joined short options
  • improved error messages
  • If you’ve used the Swift Package Manager command-line tool recently, you’ve used Swift ArgumentParser.

Update on Swift on Server

  • static linking on Linux
  • improved JSON performance
  • enhanced and optimized the performance of the AWS Lambda runtime

Developer Experience improvements

Swift DocC

  • a documentation compiler that’s deeply integrated inside Xcode 13

swift2

Performance improvements in the type checker

  • sped up the performance for type checking of array literals

Build Improvements

  • Faster builds when changing imported modules
    • no longer rebuild every source file
  • Faster startup time before launching compilers
  • Fewer recompilations after changing an extension body

swift3 swift4

Memory Management

  • ARC automatically frees up the memory used by class instances when those instances are no longer needed
class Traveler {
    var destination: String
}

func test() {
    let traveler1 = Traveler(destination: "Unknown")
    // retain
    let traveler2 = traveler1
    // release
    traveler2.destination = "Big Sur"
    // release
    print("Done traveling")
}

swift5

Ergonomic improvements

Result Builders

Enum Codable synthesis

enum Command: Codable {
    case load(key: String)
    case store(key: String, value: Int)
}

Flexible Static member lookup

  • like enum, using the same dot-notation on Structures
protocol Coffee { ... }
struct RegualrCoffee: Coffee { }
struct Cappuccino: Coffee { }
extension Coffee where Self == Cappuccino {
    static var cappuccino: Cappuccino { Cappucino() }
}

func brew<CoffeeType: Coffee>(_ coffee: CoffeeType) { ... }

brew(.capuccino.large)

Property wrappers on parameters

@propertyWrapper
struct NonEmpty<Value: Collection> {
    init(wrappedValue: Value) {
        precondition(!wrappedValue.isEmpty)
        self.wrappedValue = wrappedValue
    }

    var wrappedValue: Value {
        willSet { precondition(!newValue.isEmpty) }
    }
}

struct User {
    @NonEmpty var username: String
}

func logIn(@NonEmpty _ username: String) {
    print("\(username)")
}

SwiftUI Code

import SwiftUI

struct SettingsView: View {
    @State var settings: [Setting]

    private let padding = 10.0

    var body: some View {
        List($settings) { $setting in
            Toggle(setting.displayName, isOn: $setting.isOn)
            #if os(masOS)
            .toggleStyle(.checkbox)
            #else
            .toggleStyle(.switch)
            #endif
        }
        .padding(padding)
    }
}

Asynchronous and Concurrent programming

  • the highlight of Swift 5.5

swift6

Asynchronous : Async/Await

func fetchImage(id: String) async throws -> UIImage {
    let request = self.imageURLRequest(for: id)
    let (data, response) = try await URLSession.shared.data(for: request)
    if let httpResponse = response as? HTTPURLResponse,
       httpResponse.statusCode != 200 {
        throw TransferFailure()
    }
    guard let image = UIImage(data: data) else {
        throw ImageDecodungFailure()
    }
    return image
}

Structed Concurrency

  • async
  • it will be able to suspend if it needs to wait for results that are being computed in other threads
func titleImage() async throws -> Image {
    let background = try renderBackground()
    let foreground = try renderForeground()
    let title = try renserTitle()
    return merge(background, foreground, title)
}
  • async let : the async let syntax to run the first two operations in parallel.
func titleImage() async throws -> Image {
    async let background = renderBackground()
    async let foreground = renderForeground()
    let title = try renserTitle()
    return try await merge(background, foreground, title)
}

swift7

Actor

  • a newconstruct helps protect your data in a multi-threaded environment
// before : Concurrent code
class Statistics {
    private var counter: Int = 0
    func increment() {
        counter += 1
    }
}

// with swift actor
actor Statistics {
    private var counter: Int = 0
    func increment() {
        counter += 1
    }
}
var statistics = Statistics()
await statistics.increment()

// use async/await in actor
actor Statistics {
    private var counter: Int = 0
    func increment() {
        counter += 1
    }
    func publish() async {
        await sendResults(counter)
    }
}

Reference

Leave a comment