#wwdc #presentation [https://developer.apple.com/videos/wwdc2021](https://developer.apple.com/videos/wwdc2021) ## General [Keynote](https://developer.apple.com/videos/play/wwdc2021/101/) [Platforms State of the Union](https://developer.apple.com/videos/play/wwdc2021/102/) ## Swift [What's new in Swift](https://developer.apple.com/videos/play/wwdc2021/10192/) - Package collections in Xcode ( [https://swift.org/blog/package-collections/](https://swift.org/blog/package-collections/) ) - Xcode13 からは、Xcode 上 もしくは CLI で探してインストールすることができる - Json で collections を作成することができる (例えば社内で共有したりとか) - Swift の package をいくつかリリースした - [https://github.com/apple/swift-collections](https://github.com/apple/swift-collections) - OrderedDictionary などのデータ構造が含まれる - [https://github.com/apple/swift-algorithms](https://github.com/apple/swift-algorithms) - collection系のoperatorがたくさん入ってる - [https://github.com/apple/swift-system](https://github.com/apple/swift-system) - [https://github.com/apple/swift-numerics](https://github.com/apple/swift-numerics) - Log とか Cos とかも入ったりしてる - [https://github.com/apple/swift-argument-parser](https://github.com/apple/swift-argument-parser) - DooC というインタラクティブなドキュメンテーションを使えるように - DooC 自体は OSS になる予定 - 詳細は DooC のセッションで - Build Improvement - Faster builds when changing imported modules - 差分ビルドの恩恵が大きくなる? - モジュール化することを推奨してる感じだった - Faster startup time before launching compiles - Extension の body を変えただけの場合にもパフォーマンスを向上してる - Memory Management - ARC の retain と release のパフォーマンスを向上してる - 詳細は ARC のセッションで - Swift Evolution に基づく改善 ( [https://github.com/apple/swift-evolution](https://github.com/apple/swift-evolution) ) - Result Builders [SE-0289](https://github.com/apple/swift-evolution/blob/main/proposals/0289-result-builders.md) - 詳細はセッションで - Enum Codable Syntehsis [SE-0295](https://github.com/apple/swift-evolution/blob/main/proposals/0295-codable-synthesis-for-enums-with-associated-values.md) - Codable のボイラープレートをコンパイラで担保するように - Flexible static Member lookup [SE-0297](https://github.com/apple/swift-evolution/blob/main/proposals/0297-concurrency-objc.md) [SE-0299](https://github.com/apple/swift-evolution/blob/main/proposals/0299-extend-generic-static-member-lookup.md) - Property wrapper on parameters [SE-0293 [https://github.com/apple/swift-evolution/blob/main/proposals/0293-extend-property-wrappers-to-function-and-closure-parameters.md](https://github.com/apple/swift-evolution/blob/main/proposals/0293-extend-property-wrappers-to-function-and-closure-parameters.md) - 具体例をベースに書き方を一部改善してみる swift ``` import SwiftUI struct SettingView: 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)) } } ``` swift ``` import SwiftUI struct SettingView: View { @State var settings: [Setting] private let padding = 10.0 var body: some View { List($settings) { $setting in // ① List に対して ..< とかじゃなくてArrayをそのまま渡せる Toggle(setting.displayName, isOn: $setting.isOn) #if os(macOS) // ② #ifマクロは式みたいに機能する .toggleStyle(CheckboxToggleStyle()) #else .toggleStyle(SwitchToggleStyle()) #endif } .padding(padding) // ③ CGFloat と Double をキャストしてくれる } } ``` - Concurrency - Completion Handler パターンが今まではよくあるパターンだった swift ``` // 今までの書き方は、タスクという低レベルなものを扱っていた // task と completion handlerで書くパターン let task = URLSession.shared.dataTask(with: request) // でも本来欲しいのは、データ // ただしそれがすぐに終わらないということを `await` キーワードでコンパイラに教える必要がある let (data, response) = try await URLSession.shared.data(with: request) ``` - 非同期のセッションは非同期のセッションで詳細に扱う - Actorの話 - 非同期を扱う場合には常にマルチスレッドからのデータ変更のリスクがある - Actor を使うとマルチスレッドで安全に書き込みができる Goroutine の チャンネルみたいな概念っぽい - Swift 6 の展望 - Safe concurrency (Actor や async/await をベースに改善していく) [ARC in Swift: Basics and beyond](https://developer.apple.com/videos/play/wwdc2021/10216/) [Write a DSL in Swift using result builders](https://developer.apple.com/videos/play/wwdc2021/10253/) ## SwiftUI [What's new in SwiftUI](https://developer.apple.com/videos/play/wwdc2021/10018/) [Demystify SwiftUI](https://developer.apple.com/videos/play/wwdc2021/10022/) [SwiftUI Accessibility: Beyond the basics](https://developer.apple.com/videos/play/wwdc2021/10119/) ## Concurrency in Swift [Explore structured concurrency in Swift](https://developer.apple.com/videos/play/wwdc2021/10134/) - Structured Programming (構造的プログラミング) が現代では一般的 - 処理のフローが一方向でネストしたり合成したりできる - 非同期が一般的になってくると構造プログラミング的に理解するのが難しい - 例えば、completionHandler などはいつ処理されるかなどが複雑 - completionHandler の例外処理やそれを元にした loop などがうまく書けないことが構造的プログラミング上での課題 - Structured Concurrency - Async-let tasks swift ``` func fetchOneThumbnail(withID id: String) async throws -> UIImage { let imageReq = imageRequest(for: id), metadataReq = metadataRequest(for: id) // async let は非同期で実行され、結果の評価自体は遅延する async let(data, _) = URLSession.shared.data(for: imageReq) async let(metadata, _) = URLSession.shared.data(for: metadataReq) guard let size = parseSize(from: try await metaData), let image = try await UIImage(data: data)?.byPreparingThumbnail(ofSize: size) else { throw ThumbnailFailedError() } return image } ``` - fetchOneThumbnail のスコープと dataとmetadata の非同期処理は親子関係にあり、いわゆる非対称コルーチンの構造と同じで、木がネストしていったときに親が異常終了などした場合には、子供が中止されるなどの関係がありリークを防ぐ - Task Cancellation は as soon as possible に発生するのでキャンセルが発生するような場合にはタスクがキャンセルされているかどうかの状態ハンドリングが必要になる - Task Group - Async-let tasks は結果の数が静的に定まる場合に有効でいくつを非同期に実行するかわからない場合には Task Group を使う swift ``` func fetchThumbnails(for ids:String) async throws -> String: UIImage { var thumbnails: String: UIImage = : try await withThrowingTaskGroup(of: (String, UIImage).self) { group in for id in ids { group.async { // ここで変数の代入などはできない return (id, try await fetchOneThumbnail(withId: id)) } } for try await (id, thumbnail) in group { thumbnailsid = thumbnail } } return thumbnails } ``` - Parent Task -> group task -> async-let task という親子構造になってる - Task は @Sendable クロージャを受け取る - mutable な variable を受け取ることはできないのでマルチスレッドからの変数書き込みなどが起きないようになってる - Group にもキャンセルの概念がある - Unstructered Concurrency - 非同期 context じゃない箇所から非同期の処理を呼び出したいこともある (func に async がラベリングされていないメソッドから async メソッドを呼び出したい場合) swift ``` @MainActor class MyDelegate: UICollectionViewDelegate { var thumbnailTasks: [IndexPath: Task.Handle<Void, Never>] = [:] // async ではない context の中から async を実行したい (親タスクがない状態) func collectionView(_ view: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt item: IndexPath) { let ids = getThumbnailIDs(for: item) thumbnailTask[item] = async { defer { thumbnailTasks[item] = nil } // キャンセルされることもある let thumbnails = await fetchThumbnails(for: ids) // 新しいタスクを切り離して実行することができる // 付随して実行したいような非同期処理で実行の context を変更したいなどのユースケース asyncDetached(priority: .background) { withTaskGroup(of: Void.self) { g in g.async { writeToLocalCache(thumnbnails) } g.async { log(thumbnail) } g.async { ... } } } display(thumbnails: thumbnails, in: cell) } } // セルが削除された場合に非同期タスクをキャンセルする func collectionView(_ view: UICollectionView, didEndDisplay cell: UICollectionViewCell, forItemAt item: IndexPath) { thumnbailTask[item]?.cancel() } } ``` [Meet async/await in Swift](https://developer.apple.com/videos/play/wwdc2021/10132/) - `Completion Handler` パターンは、completion の呼び忘れや例外処理が複雑になってしまう - エラー処理に try-catch の機構が使えないので型レベルで確保できない - 改善としては、 `Result` 型を利用したり、`Future` を使ったりしていたが型レベルで確保できる方法はこれまでなかった swift ``` // 型レベルで例外が表現できてるので書くことが強制される func fetchThumbnail(for id: String) async throws -> UIImage { let request = thumbnailURLRequest(for: id) let (data, response) = try await URLSession.shared.data(for: request) guard (response as? HTTPURLResponse)?.statusCode == 200 else { throw FetchError.badID } let maybeImage = UIImage(data: data) // `thumbnail` のようなプロパティも async になれる guard let thumbnail = await maybeImage?.thumbnail else { throw FetchError.badImage } return thumbnail } // 非同期プロパティ `thumbnail` の定義 extension UIImage { var thumbnail: UIImage? { // only read only properties can mark as async get async { let size = CGSize(width: 40, height: 40) return await self.byPreparingThumbnail(ofSize: size) } } } ``` - for でも await が使える -> [Meet AsyncSequence](https://developer.apple.com/videos/play/wwdc2021/10058/) で詳細は話される - aync enbales a function to suspend and also callers to susupend - which means callers should be async as well - Briidging from sync to async swift ``` struct ThumbnailView: View { @ObservedObject var viewModel: ViewModel var post: Post @State private var image: UIImage? var body: some View { Image(uiImage: self.image ?? placeholder) .onAppear { async { // ここで async context じゃない箇所から async function を起動する self.image = try? await self.viewModel.fetchThumbnail(for: post.id) } } } } ``` [Protect mutable state with Swift actors](https://developer.apple.com/videos/play/wwdc2021/10133/) [Discover concurrency in SwiftUI](https://developer.apple.com/videos/play/wwdc2021/10019/) [Meet AsyncSequence](https://developer.apple.com/videos/play/wwdc2021/10058/) [Swift concurrency: Update a sample app](https://developer.apple.com/videos/play/wwdc2021/10194/) [Use async/await with URLSession](https://developer.apple.com/videos/play/wwdc2021/10095/) [Bring Core Data concurrency to Swift and SwiftUI](https://developer.apple.com/videos/play/wwdc2021/10017/) [Swift concurrency: Behind the scenes](https://developer.apple.com/videos/play/wwdc2021/10254/) ## UIKit [Meet the UIKit button system](https://developer.apple.com/videos/play/wwdc2021/10064/) [What's new in UIKit](https://developer.apple.com/videos/play/wwdc2021/10059/) ## Other iOS App [Discoverable design](https://developer.apple.com/videos/play/wwdc2021/10126/) [Explore WKWebView additions](https://developer.apple.com/videos/play/wwdc2021/10032/) [Detect and diagnose memory issues](https://developer.apple.com/videos/play/wwdc2021/10180/) [Diagnose unreliable code with test repetitions](https://developer.apple.com/videos/play/wwdc2021/10296/) [Distribute apps in Xcode with cloud signing](https://developer.apple.com/videos/play/wwdc2021/10204/) [Embrace Expected Failures in XCTest](https://developer.apple.com/videos/play/wwdc2021/10207/) [Discover breakpoint improvements](https://developer.apple.com/videos/play/wwdc2021/10209/) [Explore advanced project configuration in Xcode](https://developer.apple.com/videos/play/wwdc2021/10210/) ## Xcode and Xcode Cloud [Explore Xcode Cloud workflows](https://developer.apple.com/videos/play/wwdc2021/10268/) [Meet Xcode Cloud](https://developer.apple.com/videos/play/wwdc2021/10267/) [Customize your advanced Xcode Cloud workflows](https://developer.apple.com/videos/play/wwdc2021/10269/) ## DooC (Documantation Compiler) ドックシーって発音するらしい [Meet DocC documentation in Xcode](https://developer.apple.com/videos/play/wwdc2021/10166/) - Xcode13 にはドキュメンテーションのコンパイラが組み込まれてる -> DooC - 3つのタイプのドキュメントがかける - Reference - クラスの参照など - Articles - 機能の詳細の説明など - Tutorials - 2021年の終わりにOSSにする - 仕組み - ![image](https://gyazo.com/fd7d3fbb771673fe60803f6c0b226442/thumb/1000) - コードからの public な情報とそこに情報を足すみたいなイメージっぽい - `xcodebuild docbuild` や設定でビルドの頻度などを実行したりできる - 詳細は他のセッションで - Xcode上でドキュメントの詳細などを見ることができる swift ``` /// A model representing a sloth -> /// がドキュメントに反映されるコメントになる /** -> /** も反映される */ public struct Sloth { // ... } extension Sloth { /// Food ... /// /// ↓↓ 1行あけると discussion セクションになる /// xxxx /// xxxx /// ↓↓ markdown support もある /// ```swift /// func doSomething() /// ``` public struct Food { /// - Parametes: /// - a: xxx /// - b: xxx /// ``引用したい reference`` で引用もできるらしい func doSomething() { } } } ``` - ドキュメントの書き方を結構決めてくる感じのスタイルで独特 - 手で書くこともできるけど、`Add documentation` ショートカットでドキュメントを足すこともできる - Web に push したりもできる - 詳細は他のセッションで - ちなみに手動でもアーカイブを作成できたりする [Host and automate your DocC documentation](https://developer.apple.com/videos/play/wwdc2021/10236/) - DooC のHostとビルドの自動化の話 - DooC Archive を Exportから作成できる - ![image](https://gyazo.com/9aa6b0c532b54048c1f70be407219e49/thumb/1000) - ハンドリングすべき Request について - `/documentation` or `/tutorial` のリクエストは、 `XXX.doocarchive/index.html` を返す - `/css` or `/data` などのリソースリクエストも `XXX.doocarchive/css` などにルーティングする - Automating builds - `xcodebuild docbuild` で DooC をビルドできるのでCIなどでも自動化できる [Elevate your DocC documentation in Xcode](https://developer.apple.com/videos/play/wwdc2021/10167/) [Build interactive tutorials using DocC](https://developer.apple.com/videos/play/wwdc2021/10235/) ## AppStore [Meet in-app events on the App Store](https://developer.apple.com/videos/play/wwdc2021/10171/) [Get ready to optimize your App Store product page](https://developer.apple.com/videos/play/wwdc2021/10295/) - 2021年後半 に以下の2つの新機能を導入する - Custom Product pages - App preview videos, Screenshots, promotional text を編集できる - それぞれ unique url が発行される - Impressions, Downloads, conversion rates, Retention, Average proceeds per paying user をメトリックとして測定できる - 最大35種類の Custom Product pages を作成可能 - Getting Ready - Plan your goals - Consider your features and content - Prepare your metadeata (video や Screenshot など) - 新しいバージョンをリリースすることなくこの機能は導入可能 - 基本は URL を発行してシェアする形式っぽい - Product page optimization - ストアに直接きたユーザーについて ABテストするための機能 - Original と 3 treatment でテストできる - テストアイコンでインストールしたユーザーは、テストアイコンが画面に表示されるようになる - 複数の画像をアイコン画像として用意する形式になる - Impressions, Download, Conversion, Original と比較しての Improvement を測定できる [Manage in-app purchases on your server](https://developer.apple.com/videos/play/wwdc2021/10174/) ## Privacy [Apple's privacy pillars in focus](https://developer.apple.com/videos/play/wwdc2021/10085/) - メールアドレスで任意の文字列を入力できるらしい (Hide my email 機能) - メールの中1ピクセル通信をブロックできる - Record Activtiy - App の Activity を記録できる (どういうドメインに通信したかとか) - App privacy report - App Privacy Report は ユーザーがアプリが何をしているのかを明らかにするためにできた - App Tracking Transparency - 広告目的に情報を集める際には、ユーザーに許諾を求める - Educate before triggering the prompt はおすすめ - SDK などのサードパーティーも含めて開発者がが責任を持つ必要がある - iOS 15 からは、AdNetworkを使わないで効果測定ができるようにしてる - IDFAに限らず、メールアドレスなどの情報もトラッキングの対象になる - Security - IPアドレスを元にサイトでいろんな情報を統合しているサイトが多い - 明示的に提供したわけではないのに、注文時の住所情報なども露呈してしまってる - ネットワークを使ってるネットワークプロバイダもデータを集めることができてしまう - iOS15 では、Private Relay という機能機能で以下を達成する - All connections are encrypted - IP address no longer identitfy you - IP address location is protected - No single company can see what you do - ![image](https://gyazo.com/53ea5252eeeea3c647aac297acc0a7da/thumb/1000) - email address と IP address を隠すことにWeb の プライバシーはフォーカスしてるっぽい (suke) - [https://www.apple.com/jp/newsroom/2021/06/apple-advances-its-privacy-leadership-with-ios-15-ipados-15-macos-monterey-and-watchos-8/](https://www.apple.com/jp/newsroom/2021/06/apple-advances-its-privacy-leadership-with-ios-15-ipados-15-macos-monterey-and-watchos-8/) - この辺も関連していそう ## Account Management [Discover account-driven User Enrollment](https://developer.apple.com/videos/play/wwdc2021/10136/)