-
What‘s new in Swift
Join us for an update on Swift. Discover the latest language advancements that make your code easier to read and write. Explore the growing number of APIs available as Swift packages. And we'll introduce you to Swift's async/await syntax, structured concurrency, and actors.
Ressources
- Package Collections
- Swift Compiler Driver on GitHub
- Swift System on GitHub
- Swift Collections on GitHub
- Swift Algorithms on GitHub
- Swift Package Index
- Swift Mentorship Program
- Diversity in Swift
- Swift Forums
- The Swift Programming Language: Concurrency
- DocC
- Swift AWS Lambda Runtime on GitHub
- Swift Argument Parser on GitHub
- Swift Evolution
- Swift Numerics on GitHub
Vidéos connexes
WWDC21
- Build interactive tutorials using DocC
- Discover and curate Swift Packages using Collections
- Elevate your DocC documentation in Xcode
- Explore structured concurrency in Swift
- Host and automate your DocC documentation
- Meet async/await in Swift
- Meet DocC documentation in Xcode
- Meet the Swift Algorithms and Collections packages
- Protect mutable state with Swift actors
- Swift concurrency: Behind the scenes
- What's new in SwiftUI
- Write a DSL in Swift using result builders
WWDC20
-
Rechercher dans cette vidéo…
-
-
6:16 - Deque
import Collections var colors: Deque = ["red", "yellow", "blue"] colors.prepend("green") colors.append("orange") // `colors` is now ["green", "red", "yellow", "blue", “orange"] colors.popFirst() // "green" colors.popLast() // "orange" // `colors` is back to ["red", "yellow", "blue"] -
6:25 - Ordered set
import Collections var buildingMaterials: OrderedSet = ["straw", "sticks", "bricks"] for i in 0 ..< buildingMaterials.count { print("Little piggie #\(i) built a house of \(buildingMaterials[i])") } // Little piggie #0 built a house of straw // Little piggie #1 built a house of sticks // Little piggie #2 built a house of bricks buildingMaterials.append("straw") // (inserted: false, index: 0) -
6:42 - Ordered dictionary
import Collections var responses: OrderedDictionary = [200: "OK", 403: "Forbidden", 404: "Not Found"] for (code, phrase) in responses { print("\(code) (\(phrase))") } // 200 (OK) // 403 (Forbidden) // 404 (Not Found) -
7:39 - Swift Algorithms
import Algorithms let testAccounts = [ ... ] for testGroup in testAccounts.uniquePermutations(ofCount: 0...) { try validate(testGroup) } let randomGroup = testAccounts.randomSample(count: 5) -
7:52 - Swift System
import System let fd: FileDescriptor = try .open( "/tmp/a.txt", .writeOnly, options: [.create, .truncate], permissions: .ownerReadWrite) try fd.closeAfter { try fd.writeAll("Hello, WWDC!\n".utf8) } -
8:06 - FilePath manipulation APIs
import System var path: FilePath = "/tmp/WWDC2021.txt" print(path.lastComponent) // "WWDC2021.txt" print(path.extension) // "txt" path.extension = "pdf" // path == "/tmp/WWDC2021.pdf" path.extension = nil // path == "/tmp/WWDC2021" print(path.extension) // nil path.push("../foo/bar/./") // path == "/tmp/wwdc2021/../foo/bar/." path.lexicallyNormalize() // path == "/tmp/foo/bar" print(path.ends(with: "foo/bar")) // true! -
9:01 - Float16 support on Apple silicon Macs
import Numerics let x: Float16 = 1.5 let y = Float16.exp(x) -
9:05 - Complex elementary functions
import Numerics let z = Complex(0, Float16.pi) // πi let w = Complex.exp(z) // exp(πi) ≅ -1 -
11:07 - AWS Lambda runtime now with async/await
import AWSLambdaRuntime import AWSLambdaEvents @main struct HelloWorld: LambdaHandler { typealias In = APIGatewayV2Request typealias Out = APIGatewayV2Response func handle(event: In, context: Lambda.Context) async throws -> Out { .init(statusCode: .ok, body: "Hello World") } } -
14:52 - Memory management
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") } -
17:04 - Codable synthesis for enums with associated values: A two-case enum
enum Command { case load(key: String) case store(key: String, value: Int) } -
17:11 - Codable synthesis for enums with associated values: Before
// You used to have to manually implement all of this boilerplate. enum Command: Codable { case load(key: String) case store(key: String, value: Int) init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) if container.allKeys.count != 1 { let context = DecodingError.Context( codingPath: container.codingPath, debugDescription: "Invalid number of keys found, expected one.") throw DecodingError.typeMismatch(Command.self, context) } switch container.allKeys.first.unsafelyUnwrapped { case .load: let nested = try container.nestedContainer( keyedBy: LoadCodingKeys.self, forKey: .load) self = .load( key: try nested.decode(String.self, forKey: .key)) case .store: let nested = try container.nestedContainer( keyedBy: StoreCodingKeys.self, forKey: .store) self = .store( key: try nested.decode(String.self, forKey: .key), value: try nested.decode(Int.self, forKey: .value)) } } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) switch self { case let .load(key): var nested = container.nestedContainer(keyedBy: LoadCodingKeys.self, forKey: .load) try nested.encode(key, forKey: .key) case let .store(key, value): var nested = container.nestedContainer(keyedBy: StoreCodingKeys.self, forKey: .store) try nested.encode(key, forKey: .key) try nested.encode(value, forKey: .value) } } /// Contains keys for all cases of the enum. enum CodingKeys: CodingKey { case load case store } /// Contains keys for all associated values of `case load`. enum LoadCodingKeys: CodingKey { case key } /// Contains keys for all associated values of `case store`. enum StoreCodingKeys: CodingKey { case key case value } } -
17:15 - Codable synthesis for enums with associated values: After
enum Command: Codable { case load(key: String) case store(key: String, value: Int) } -
17:26 - Static member lookup
enum Coffee { case regular case decaf } func brew(_ coffee: Coffee) { ... } brew(.regular) -
17:49 - Flexible static member lookup
protocol Coffee { ... } struct RegularCoffee: Coffee { } struct Cappuccino: Coffee { } extension Coffee where Self == Cappucino { static var cappucino: Cappucino { Cappucino() } } func brew<CoffeeType: Coffee>(_ coffee: CoffeeType) { ... } brew(.cappucino.large) -
18:25 - 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) } } } func logIn(@NonEmpty _ username: String) { print("Logging in: \(username)") } -
19:02 - Ergonomic improvements in SwiftUI code: Before
// Instead of writing this... import SwiftUI struct SettingsView: View { @State var settings: [Setting] private let padding = 10.0 var body: some View { List(0 ..< settings.count) { index in #if os(macOS) Toggle(settings[index].displayName, isOn: $settings[index].isOn) .toggleStyle(CheckboxToggleStyle()) #else Toggle(settings[index].displayName, isOn: $settings[index].isOn) .toggleStyle(SwitchToggleStyle()) #endif } .padding(CGFloat(padding)) } } -
19:37 - Ergonomic improvements in SwiftUI code: After
// You can now write this. 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(macOS) .toggleStyle(.checkbox) #else .toggleStyle(.switch) #endif } .padding(padding) } } -
22:20 - Asynchronous programming with async/await: Before
// Instead of writing this... func fetchImage(id: String, completion: (UIImage?, Error?) -> Void) { let request = self.imageURLRequest(for: id) let task = URLSession.shared.dataTask(with: request) { data, urlResponse, error in if let error = error { completion(nil, error) } else if let httpResponse = urlResponse as? HTTPURLResponse, httpResponse.statusCode != 200 { completion(nil, MyTransferError()) } else if let data = data, let image = UIImage(data: data) { completion(image, nil) } else { completion(nil, MyOtherError()) } } task.resume() } -
23:58 - Asynchronous programming with async/await: URLSession.shared.data(for:)
let (data, response) = try await URLSession.shared.data(for: request) -
24:40 - Asynchronous programming with async/await: After
// You can now write this. 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 ImageDecodingFailure() } return image } -
27:06 - Structured concurrency
func titleImage() async throws -> Image { async let background = renderBackground() async let foreground = renderForeground() let title = try renderTitle() return try await merge(background, foreground, title) } -
29:26 - Actors
actor Statistics { private var counter: Int = 0 func increment() { counter += 1 } func publish() async { await sendResults(counter) } } var statistics = Statistics() await statistics.increment()
-