ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
Swiftの新機能
Swiftのアップデートを紹介します。簡単にコードを読み書きできるようにする最新の言語拡張内容について解説します。Swiftパッケージとして利用できるAPIの増加を検証し、Swiftのasync/await構文、構造化された並列処理、アクターについて説明します。
リソース
- Diversity in Swift
- DocC
- Package Collections
- Swift Algorithms on GitHub
- Swift Argument Parser on GitHub
- Swift AWS Lambda Runtime on GitHub
- Swift Collections on GitHub
- Swift Compiler Driver on GitHub
- Swift Evolution
- Swift Forums
- Swift Mentorship Program
- Swift Numerics on GitHub
- Swift Package Index
- Swift System on GitHub
- The Swift Programming Language: Concurrency
関連ビデオ
WWDC21
- コレクションを使用したSwiftパッケージの発見とキュレーション
- リザルトビルダーを使用したSwiftでのDSLの記述
- DocCを使ったインタラクティブなチュートリアルの製作
- DocCドキュメントのホストと自動化
- Swift AlgorithmsパッケージとSwift Collectionsパッケージについて
- Swiftにおける構造化並行処理
- Swiftの並行処理: 舞台裏
- Swiftのasync/awaitについて
- Swiftアクターによるミュータブルステートの保護
- SwiftUIの新機能
- XcodeにおけるDocCドキュメントについて
- XcodeにおけるDocCドキュメントのレベルの向上
WWDC20
-
ダウンロード
♪ ♪ こんにちは Nicoleです ようこそ 「Swiftの新機能」へ Swift 5.5は最高のリリースです Swiftは急速に進化し Swiftでの並行処理を より便利で効率よく安全に行えるよう デザインされた新しい非同期及び 並行処理のための新機能 Swift Concurrencyなどが 追加されました さらにパッケージの向上や 新しいライブラリ デベロッパー体験の向上機能などで Swiftでのプログラミングが 非常に簡単になりました
これらの向上も大切ですが Swiftプロジェクトの核心は コードではなく Swiftのために 努力を重ねる人々の コミュニティーです ですので ソフトウェアだけでなく コミュニティーに 投資するのが重要なのです まず 大切なSwiftの コミュニティーイニシアチブの お話です Swiftコミュニティーでは 多様性がコア・バリューです 多様なオープンソースプロジェクトは 生産的で決断にも優れると 調査で判明しています いろんな環境の人達と多様な見方は コミュニティーの繁栄につながります Diversity in Swiftイニシアチブで 幅広いデベロッパーのみなさんに Swiftエコシステムとコミュニティーで 活発に活動していただけると 考えました Diversity in Swiftの目的は どのような環境にも関わらず デベロッパーからいろんな声を聞き Swiftを学びやすく貢献しやすくし 包括的なコミュニティーを 育成することです それに基づいて swift.orgのブログを拡張し コミュニティー内の 様々なデベロッパーの 貢献を認識・賞賛する記事を 掲載しています また 同じような経験や問題に面した デベロッパーと連絡しあえるよう Swift forum内に コミュニティーグループを 作成しました Diversity in Swiftに参加したり 詳細をお求めなら swift.org/diversity をご覧ください またコミュニティーに 既存のデベロッパーにも Swiftで目標を達成していただくため Swiftオープンソースプロジェクトに 貢献できやすいよう 初心者が支持や指導を受けられる Swiftメンターシップ プログラムを開始しました これはAppleの プロジェクトにとどまらず Swiftとオープンソースツールの 全エコシステムをカバーしています 次にパッケージについてです パッケージはソフトウェア構築の 基礎であり 拡張を続けるオープンソースコードを 手軽に利用できます コミュニティーのメンバーが パッケージを発見しやすい方法を 考えつきました Swift Package Indexがその例です コミュニティーによって作られ Swift Package Managerをサポートする パッケージを検索できるページです Swift 5.5 と Xcode 13 で さらに多くの方法で パッケージにアクセスできます Xcode tooling supportを 統合することで ワークフロー上での パッケージの使用が 非常に簡単になりました
Swift Package Collections が 今年度 デビューします コマンド・ラインと Xcode 13の両方で使える 精選されたパッケージリストです これでインターネットを 検索せずに済み URLのコピペも不要になります Xcode の File > Add Packages で ブラウズし足すだけです これらのパッケージは JSONファイルで どこでもパブリッシュできます どのような使用方法でも これらのパッケージを使用できます 例えば コンピューターの クラスの講師が クラスで教えるために パッケージを使用したり ドメインやタスク もしくは組織のために パッケージを 使用することもできます いろんな方法で ご利用いただければと思っています パッケージコレクションに関する プレゼンがありますので ぜひ ご覧ください パッケージコレクションには Xcodeでのパワフルな ツールサポートがあります お気に入りのAPIsをすぐに使えます インポートしようとする モジュールがない場合 Xcodeはパッケージコレクションに そのモジュールがないか確認し あればそのモジュールを自動的に 使用できるよう手配します パッケージを使うと決めれば パッケージコレクションの 情報に基づき 全て自動的に設定されます パッケージコレクションは検索可能で 必要に応じたものを 探すことができます もし今日お試しになりたいなら GitHubにある AppleのSwiftパッケージなどが 既に利用可能です XcodeはAppleコレクションを いつでも使用できます
コミュニティーで 既に利用可能なパッケージなど パッケージコレクションに関しては swift.orgのパッケージコレクションの ブログをご参照ください お気に入りのAPIsと言えば Appleには未だ拡張中の Swiftパッケージがあります お気に入りのパッケージの 機能大改善に加え 今年は 新パッケージが4つ加わります まずSwift Collectionsについてです
Swift Collectionsは Swift Standard Libraryを補足する データ構造に関する オープンソースパッケージです Swift Collectionsの最初のバージョンは 最もよくリクエストされる 3つのデータ構造からなります Deque と OrderedSet と OrderedDictionary です
Deque は Array のようですが 両先端で追加および削除ができます OrderedSet は Array と Set の パワフルなハイブリッドです Array のように OrderedSet は 順序を保持し ランダムアクセスが可能です Set のように OrderedSet は 要素が一度だけ現れ 効率的な membership testing を 提供します
OrderedDictionary は順序が重要か 要素にランダムアクセスが必要な時 Dictionary の代わりになります 続いて Swift Algorithms は Sequence と Collection algorithms の オープンソースパッケージです
既に40以上のアルゴリズムが 追加されています 集めた要素の配合や順列の発生 要素を2や3もしくは 述語で決められたグループで 繰り返したり コレクション内の最小・最大5要素や ランダムに選ぶなどです
用語を学ぶのに努力が必要ですが いざ学べばどれだけのアルゴリズムが 発見できるか驚きです
Swift Algorithms と Collections パッケージで コードがどれだけ明確で速く 正確になるかという セッションがあります では Swift System についてです 昨秋 慣用的で軽レベル インターフェイスを システムコールに提供するライブラリ Swift System を オープンソース化しました Appleプラットフォームや Linux と Windows でも利用できます パス操作の処理のために System の FilePath タイプに 新しいパワフルなAPIを追加しました これらは query や extensions のセット コンポーネントの追加や削除 パスの正規化ができます path は root と components に 分解されます FilePath の ComponentView は 構造化されたパスコンポーネントの コレクションで Swift の一般なアルゴリズムを サポートしています
Windows では Windows paths と complex root components が FilePath APIsでサポートされています 続いて Swift Numerics です Swift Numerics には今年 多くの改良が加わりました 昨年 iOS・tvOS・watchOS に Float16 を追加しました 今年は Float16 サポートと Float16 ベースの complex numbersサポートを Apple Silicon Macs に追加 さらには log・sine・cosine などの complex numberの サポートの追加です これらは Swift で書かれているため Cライブラリーより 効率がよく これまで不可能だった 最適化が可能になります そして Swift Argument Parser です Swift Argument Parser の 洗練は今年も続き code-completion scripts の Fish shell への生成や joined short options や エラーメッセージの 改良などがあります また この春 Xcode 12.5 で Argument Parser が Swift Package Manager に 採用されました そうです 最近 Swift Package Manager の command-line ツールを使ったなら Swift Argument Parser を 使ったということです 続いては server development における Swift のサポートについてです 昨年 Amazon Linuxを含む 多くのプラットフォームの サポートを追加しました 今年はSwift server applicationsの パフォーマンスと機能に 努力を費やしました
Linux の static linking を可能にし Appの立ち上げ時間が向上し server applications のデプロイも シンプルになりました 今では単一ファイルとして デプロイできます また Swift 5.5 では Linux の JSON エンコードとデコードが 再実装され多くのケースで パフォーマンスが向上しました そして AWS Lambda runtime library の パフォーマンスを向上しました これにより AWS Lambda で Swift のパフォーマンスが 33%速くなり lambda routed via AWS API Gatewayでは 呼び出し時間が40%速くなりました さらに AWS runtime library の最適化に加え クロージャの 代わりに 新しい async/await model を 使用するようリファクターしました Swift でのデベロッパーの 経験を向上させるのも Swift 5.5 のもう一つのフォーカスです まず ドキュメンテーションに ついてです ユーザーにとって ドキュメンテーションは スムーズでいい経験に重要です 今年は DocC をご紹介します これは Swift フレームワーク 及びパッケージの 使い方をデベロッパーに教えるための Xcode 13 内に取り入れられた ドキュメントコンパイラです これでドキュメントの制作と共有が 非常に楽になります
DocC は一から作られ Swift source code の markdown comments のような ツールと技術を使用しているため ドキュメントの制作と diff が 非常に簡単です
Xcode の DocC に関する セッションが4つあります ぜひ ご覧になってください 非常に嬉しい発表です Swift DocC は今年後半 オープンソース化されます これにより Swift がサポートする 全てのプラットフォームにおいて ドキュメントの作成が 非常に楽になります
Swift 5.5 では type checker の 質と性能向上に努力しました これによりコード編集時の "expression too complex"エラーが 少なくなるでしょう また array literals の type checking を速くしました
また このリリースでは 3つの改良点により デベロッパーの生産性を高めています まず incremental imports の サポートです つまり モジュールの変更時 ファイルを全てリビルドする 必要がなくなります さらに モジュールの依存グラフを 先に計算するため 編集したもののみの インクリメンタルビルドが できるのです そして extention の選択的 再コンパイルを拡大しました つまり extention の変更時の 再コンパイルが少なくなります 例えば SwiftDriver オープンソース プロジェクトの場合 インクリメンタルインポートは Swift 5.5で変更されたモジュールを インポートした時 リコンパイルするファイルは 以前の10分の1以下で ビルド時間は3分の1になります インクリメンタルインポートによる パフォーマンス向上で ビルドパフォーマンスに影響なく プロジェクトをモジュール化し インポートしたモジュールを 変更できるのです ところでパフォーマンス 向上のいくつかは Swift プロジェクトにおける 重要な偉業で 達成できました コンパイラの最初の部分が Swift で書かれたのです これが Swift ソースコードの コンパイルを調整する Swift Driver です このプロジェクトは 2019年に始まり Xcode 13 で Swift コンパイルの デフォルトになりました 最後に Swift がメモリーを 素早く再利用するための メモリーマネージメントの 効率化についてです Swift のクラスインスタンスは Automatic Reference Counting ARCを使用し オブジェクトに対し どれだけ参照があるか探知します つまり たいていの場合 Swift 内での メモリーマネージメントは 考える必要がないということです インスタンスが必要無くなれば ARCが自動的に メモリーを解放します このためにSwift コンパイラは 参照が作られる度に リテイン操作を挿入し 参照の使用が止まれば リリースします 今年コンパイラで リテインとリリース操作を減らすため コンパイラ内で参照を探知する 新しい方法を登場させました これにより著しいパフォーマンスと コードサイズの向上が見られます コード上でのこのARCの 最適化を見られるよう Xcode の設定に Optimize Object Life を追加しました ARCに関しては ARC in Swift をご参照ください
これらは Swift 5.5 の 向上点の一部にすぎません 続いて Tim が Swift Concurrency と その他の発展についてお話しします ありがとう Nicole Swift Concurrencyの 話を始める前に 毎日のプログラミングを 単純化し向上させる その他の変化についてお話しします
これらは人間工学的な 向上のリストです SE番号はSwift Evolution proposalsの識別番号です これらはメンバーが書き Swift Evolution forum で論議され Swift Core Teamに承認され languageに受諾されました 承認・却下 また議論中にも関わらず すべてのSE proposalsは GitHubのSwift Evolution repositoryにあります いくつか見てみましょう まずresult buildersです SwiftUIが発表された時 複雑なオブジェクト階層を 素早く簡単に表す 新しい文法が紹介されました 昨年 この文法が標準化され Swift Evolutionプロセスで 精錬され より簡単に より多くのコンテキストで 使用できるようになりました このパワフルな技術を ご利用になりたければ result buildersを使った セッションをご覧ください Codableプロトコルは データのシリアライズに便利ですが これまでずっと 足りないものがありました この2つのcaseのenumを見てください Codableに従うために このお決まりの処理はすべて 自分で実装する必要がありました これからはCodableを付けるだけで 残りはコンパイラに任せられます
またSwift型チェックにも 改良を加えました Swiftの型推定は 余分な情報を削減できます この例えでは Coffee.regular を .regular に省略できます しかしenumのような構造は 別の形で表示されます 例えば プロトコルに従う型の コレクションがあり APIで型推定を使いたいとします これからはenumsに使う 同じドット表記で インスタンスを参照できます プロトコルで静的 プロパティを示すだけです これはSwift型チェックの 向上で可能になり 一般的コンテキストで 静的プロパティを 一般的に分別できるからで この例にある.largeのような 連なったプロパティーの 参照も含みます これにより自然で簡単に 使えるenumのようなAPIの 洗練されたデータモデルを 構築できます
プロパティラッパーも向上しました
プロパティラッパーはプロパティに 共通のセマンティックを適用できる 便利なツールです @propertyWrapperを使って プロパティラッパーを 実装した方も多いでしょう プロパティが空白にならぬよう 必要条件を足す例です SE-0293の履行により 同じプロパティラッパーが関数と クロージャの引数で使用できます
累積的にこれらの変更によって コーディングでよくある 問題を単純化できます 簡単なSwiftUIコードサンプルで これらを見てみましょう このSwiftUI Viewには プロパティが1つあり 設定とそれらの設定の リストがあるbody そのリスト一つ一つに toggleがあります このコードを使いSwift 5.5の新機能が どのように簡略化するか 見てみましょう まずToggle initializerが 明らかに重複しています この重複は必要でしたが #ifの使用条件を緩和することで toggleStyleなどの修飾子を 取り囲むことにより 重複を無くすことができます SwiftUIは先程話した 型チェックの改良も 利用できるよう更新されています ですのでより多くの箇所で ドット表記を使用できます settings配列でindexを指定し そのクロージャ内で配列を インデックスするのは少し不便です 値のステップスルーの 方がいいでしょう これからはバインディングを 直接Listコンストラクタに渡して 配列を再度処理できます プロパティーラッパーの 引数のサポートで クロージャの引数を$で表記でき settingをまとめて処理できます ラップされた値とバインディング 両方にアクセスできます そしてSwiftコンパイラは CGFloatとDoubleを 明確に変換するため Apple APIにおいて 余分な数値変換を除去できます ご覧のように言語のコアを 精錬し続けることで 毎日のコーディングが より簡単になり内容豊富で簡単なAPIを 構築できる機会が 増えることになります SwiftUIプログラミングの 改良点などについては 「SwiftUIの新機能」をご参照ください もちろんSwift 5.5のハイライトは 非同期と並行プログラミングを サポートするインタロック機能です その紹介の前に 非同期と並行について 説明しましょう ソフトウェアプロジェクトは 何らかの指示を実行する コードブロックで形成します 単純な場合 ブロック毎に 順番に実行されます しかし他の構造もあります 例えば ネットワークのAPIは たいてい非同期スタイルで デザインされています これらのAPIではリモートサーバーに リクエストを送った後 長時間の遅延の後 返答を受け取りさらに作業が必要です 理想的にはこの遅延の間 返答に対する作業ができるまで リソースの節減にコードを 停止させたいものです それと比べて並行コードは 2つ以上のコードブロックを 実行させたい時のコードです これらは独立かつ 関連するオペレーションです ビデオのフレームの処理や ML classifierの 次期反復をUIの更新と同時に 行うことなどが その例になります それらを念頭に Swiftの新機能を使わない 非同期プログラムの例を 見てみましょう iOSやmacOSの プログラミング経験があれば このようなコードに何度も 出くわしているでしょう これはFoundationの URLSession クラスを使い ネットワークを呼び出します dataTask メソッドは 非同期オペレーションです クロージャの引数で呼び出し 結果が出れば その処理のためクロージャが 呼び出されます 非同期コードの表示に クロージャを使うのは 少し不便な処理になります このコードを見ればわかるでしょう 最初の設定の後 dataTaskによって タスクハンドラーが得られます バックグラウンド処理を 開始するためタスクハンドラーを実行 fetchImageがこの時点で返ってきます するべき処理を していないにも関わらず 処理を続けなくてはなりません ネットワーク処理が終了後 このクロージャが リザルトに取り掛かります すべてうまくいくことを願って 完了ハンドラーに 最終リザルトを送ります 非常にわずらわしい実行順序の上 完了ハンドラーの使用により try / catch のエラー処理が使えません dataTaskが完了ハンドラーに 余分なエラー引数を出し エラー毎に 完了ハンドラーを 呼び出さねばなりません Swift 5.5がこれをどう向上させるか この行を見てみましょう この呼び出しが バックグラウンドの操作を表す アブストラクトハンドルである タスクを返すことに注目してください それは私たちが望んでいることでは ありません データが欲しいだけです では どうなるか見てみましょう HTTPですので response メソッドが必要です 関数はデータを2つリターンします 1つ目は実際のデータ 2つ目は付加的データです 関数呼び出しとして データを戻す構成ですので try / catch エラー処理を使って 先例の規定手順を削除できます 少しのシンタックスでコンパイラに data メソッドが始まれば 関数は一時中止され そのオペレーションが終了するまで 仕事を終えられないことを 伝えねばなりません 新しいawaitがその役目を果たします では 見てみましょう これは現在のfetchImage 関数です 非常にわかりやすいかと思います 実行は上から下へと流れ ネストしたクロージャも不必要で try / catch エラー処理を使えます awaitは fetchImage 関数を中断する箇所を示し 決められた出来事が起こるまで 処理を継続しません
この場合 URLSessionが リクエストを開始後すぐ 他で処理が実行される間 この処理はSwiftランタイムにより 中断されます 成功であれエラーであれ 最終結果が出た時 処理は続行されます 成功ならデータと response variablesの 初期化を完了させます エラーがあれば 該当箇所に戻します 非同期処理は中断中 リソースを使いません スレッドをブロックしないのです これによりSwift ランタイムが 他の仕事に スレッドを使えるわけです 数多くの非同期処理で スレッドの共有が少なくなるわけです
統語的にasyncとawaitのキーワードは よく似た意味で使われます asyncは中断を サポートする関数だという 関数宣言です awaitはasync 関数や メソッド及びクロージャを マークするものです もちろん 実際にはこれよりもっと 面白いものです 詳細は「Swiftのasync/awaitについて」 及び「Swiftの並行処理: 舞台裏」を ぜひ ご覧ください 続いてasync/await コンセプトを基盤にした Swiftの新しい非同期 サポートを見てみましょう
これは3つのイメージを レンダリングし 組み合わせる処理です このように この処理は シーケンシャルです 背景・前景・タイトルが 順番にレンダリングされ 前のレンダリングが 完了するまで次は始まりません 並行してレンダリングさせたいものの 別々のスレッドの処理では 十分ではなくまたマージ処理は 3つの結果が出るまで 待たねばなりません 先程お話しした 非同期コーディングに似ています この処理をasyncとし 別のスレッドの処理が終えるまで 処理の一時停止が 可能になるようにします 次にasync let シンタックスで 最初の2つの処理を並行に行います async letは変数設定の ように見えますが 基本的にはその通りです しかし この場合結果を使うまでは 他のコードと並行に処理されます 背景と前景の変数が async letで初期化されるため 必要であればSwift ランタイムは それらの数値が確定するまで マージ処理を停止します マージ処理にはawaitを 使用します このコードの最も重要な点は バックグラウンドタスクは この処理より長引けないことです つまり言い換えれば バックグラウンドの 2つのタスクが稼働中は 処理が返りません この処理のどこかで エラーが出ても Swift ランタイムは タスクの終了を待ちます ここにあるtryはタイトルイメージの 計算を示しますが エラーに関してもスレッドが違っても 同様に適用されます 敏感に反応させるため エラーがあればSwift ランタイムは 未完了タスクに 完了させる機会を与えます Structured Concurrencyで このキャンセルメカニズムと async let シンタックスの 適応性ある代替について 詳細を知ることができます Swift 5.5が鍛練・構造化された形で いくつものスレッドでの処理を 簡単にすると話しました もちろんそれでは不十分です 2つのスレッドがデータを共有すると データが矛盾したり破損している 可能性があります Swiftのactor constructは それらの問題に対し データを守ります それではまた見覚えあるコードを 例にしてみましょう 統計を集めるクラスがあります counterなど その他のコードがあり 何か起こればそれを更新する increment メソッドを使用します 残念ながらマルチスレッドシステムで このコードはうまく行きません 複数のスレッドが increment メソッドを 同時に呼び出すと統計が 破損するかもしれません このクラスをSwift actorに変えると そのような破損を防げます Actorsはデータ破損を 起こしかねない処理を 安全になるまで停止させるのです つまりactor外から actor メソッドを使う時は awaitを使う必要があるということです またActorsはasync/awaitと シームレスに稼働します このpublish メソッドに asyncを使うことで ネットワークを待つ間 一時停止が可能になります そしてネットワークを待つことも データ破損を心配することもなく このactorで他のメソッドを 処理できるのです Actorsはクラスのように リファレンス型ですが マルチスレッド環境でも使えるよう 数々のルールに 従うようになっています データをactorsに パッケージすることで データに同時にアクセスし Swift コンパイラと ランタイムがデータの破損を 起こさぬよう アクセスを調整するよう 明確に伝えます もちろん Swiftのactor constructに 関するセッションがあります これをフルに活用する方法を そこで学ぶことができます このセッションを終える前に Swiftの将来についてお話ししましょう Swift 5.5で紹介した 3つのキーコンセプト 非同期処理 構造化された並行性とactorsは 安全で高性能なコード作りの いい基盤です Swift 6ではコンパイラが 開発段階初期において 並行性の間違いを発見し エラーの詳細と 修正方法を提供できるよう 既にリサーチを進めています 我々のゴールは よくある並行性の欠陥を 完全に削除し 非同期及び並行プログラミングを 他のプログラミング並みに シンプルにすることです もちろんこれらの概念に対する コンパイラの理解を 向上させると同時に これらを使ったコードの効率を 向上させる努力も続けています
Swiftはインプット歓迎の オープン共同研究です Swift 6をより良くするため Swift 5.5の経験をお知らせください 現実のApp開発において 新機能がどう役に 立っているでしょう? swift.orgのコンパイラ snapshotsを お試しください 開発途中ながらも snapshotsを提供することで Xcodeにインストールし 新機能をお試しいただけます snapshotsを利用して頂くと 次世代のSwiftの役に立つのです Swift forumsはこのプロジェクトの 源泉です 今日 ご紹介した機能はすべて Swift Evolution forumで 提案されたものです 多様な人々のおかげで 提案が精錬されたのです また 新規ユーザーのための ヘルプエリアや Swiftコミュニティーの ニュース交換など Swiftに関する数々のforumがあります その他にもSwiftを向上させる 数々の方法があります このセッションの初めに Nicoleがお話しした メンターシップもその例です 唯一の必要条件はSwiftを みなさんのために向上 させたいという願いだけです みなさんのご参加を お待ちしています [明るい音楽]
-
-
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()
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。