ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
Swiftの新機能
Swiftの最新情報を紹介するセッションです。過去10年にわたるSwiftの歴史を簡単に振り返って、Swiftコミュニティがワークグループを通じて成長し、パッケージエコシステムを拡大して、プラットフォームのサポートを向上させてきた、その歩みを学びます。データ競合の安全性をデフォルトで実現する新しい言語モードと、制約の多いシステム上でのSwiftの実行を可能にする言語サブセットをご紹介します。また、コピー不可の型、型指定されたthrow、C++との相互運用性の向上など、言語面の変更点についても見ていきます。
関連する章
- 0:00 - Introduction
- 0:12 - Swift over the years
- 3:44 - Agenda
- 3:58 - Swift project update
- 4:08 - Community
- 4:59 - Packages
- 5:50 - Blogs
- 6:33 - Swift everywhere
- 7:37 - Cross compilation to Linux
- 11:27 - Foundation
- 13:06 - Swift Testing
- 14:34 - Improvements to builds
- 16:15 - Swift's new space
- 17:03 - Language updates
- 17:29 - Noncopyable types
- 19:55 - Embedded Swift
- 21:47 - C++ interoperability
- 23:34 - Typed throws
- 26:07 - Swift 6 language mode and data-race safety
- 28:43 - Low-level synchronization primitives
- 29:59 - Wrap up
リソース
- Forum: Programming Languages
- Install Swift
- Swift 6 Migration Guide
- Swift Blog
- Swift Community Overview
- Swift Forums
- The Swift Programming Language
関連ビデオ
WWDC24
- 明示的にビルドされたモジュールについて
- Embedded Swiftでサイズを縮小
- Swift 6へのアプリの移行
- Swift Testingについて
- Swift Testingの詳細
- Swiftでのコピー不可な型の使用
- Swiftのパフォーマンスの詳細
WWDC23
-
ダウンロード
こんにちは 「What’s new in Swift」へようこそ Mishalと申します 同僚のMeghanaも後で参加します 今年はSwiftプロジェクトにとって 大きな節目の年です WWDC2014でSwiftが発表されてから 10年が経ちます
翌年にはオープンソース化され Linuxでも利用可能になりました また 言語と標準ライブラリのための コミュニティ主導の進化プロセスも 導入しました 2016年には Swift 3と共に Swift Package Managerを導入しました これは新しい進化プロセスを使用した 最初の言語バージョンで 80以上の言語提案が含まれていました Swift 2からSwift 3への移行を 経験された方は あれがいかに難しい移行だったかを 覚えているかもしれません その経験から学び Swift 4では すべてのSwiftコードを 一度に移行することなく 新しい言語モードを導入する方法を 見いだしました 同じコンパイラが 複数の言語モードをサポートできるため Swift 3とSwift 4でコンパイルされた モジュールを同じプログラムで 自由に混在させることができます この新しいアプローチによって エコシステム全体で新しい言語モードを 段階的に採用できるようになり すべてのデベロッパが 準備が整ったときに 移行できるようになりました 2018年には ジェネリクスシステムが改良されて 今日のSwiftでは当たり前となった 条件付き適合などの機能が加わり それが次の重要なリリースへの 踏み台ともなりました Swift 5では Appleプラットフォーム上の 安定版ABIが導入されました アプリデベロッパにとってはアプリの ダウンロードサイズが小さくなり アプリに完全な Swift標準ライブラリの コピーをバンドルする 必要がなくなりました 代わりに Swift標準ライブラリは OS自体の一部となり 最適化され すべてのSwiftアプリや フレームワークで共有されるようになりました これは根本的な変化を表しています なぜならSwiftの表現力をフルに活用して より優れた安全なAPIとフレームワークを 構築することができるようになったからです そして Swiftのユニークな機能を活かして UIアプリを より良くより迅速に構築する SwiftUIの導入が行われました 2020年までに Swiftは より多くのプラットフォームに対応し コミュニティによるWindowsへの移植が swift.orgで公式に利用可能となりました 我々は Async/Awaitを備えた 並行処理モデルを導入し アクターや構造化並行処理を導入しました
翌年には 分散アクターを導入し ネットワークサービスの構築を 容易にしました また 並行処理モデルの改良も続けています 同じ年に コミュニティでVSCode用の Swift拡張機能がリリースされ Swift開発のためのクロスプラットフォーム 編集体験が提供されました
昨年には C++との双方向の 相互運用性を組み込みました これにより Swiftの安全性と表現力を活用して 大規模なクロスプラットフォームの C++コードベースを簡単に 改善できるようになりました また 繰り返しのボイラープレートを削減し SwiftDataのような さらに表現力豊かな新世代のAPIを 実現するマクロを導入しました
これがSwift 6に至るまでの経緯です Swift 6は携帯性 パフォーマンス そして デベロッパの全体的な体験を向上させます またSwift 6の言語モードも導入しており データレースの安全性を保証することで 正しい並行プログラムを 記述できるよう支援しています
ここではSwiftプロジェクトの主な成果と 新しい投資について確認していきます また Swiftを利用できる 新しい場所についても見ていきます さらに 新しい言語モードのSwift 6を含む いくつかの新しい言語機能についても お話しします Swiftプログラミング言語は 大きなエコシステムの一部であり そこにはツールやパッケージ そして皆さんのようなデベロッパを含む 活発なコミュニティが含まれています ここでこのコミュニティがどのように 進化してきたかをお話ししましょう Swift Coreチームは当初 唯一の運営グループで 言語の進化プロセスやその他さまざまな 責任を担っていました コミュニティが成長するにつれて ここ数年で運営グループと ワークグループの数を増やしてきました 今年はSwiftをより多くの場所に 導入するためのプラットフォーム運営 グループを立ち上げました さらに Swift Coreチームは デベロッパの体験と より広範なエコシステムに焦点を当てた 新しいエコシステム運営グループの設立にも 積極的に取り組んでいます 低レベル環境の勢いを維持するために Swift Coreチームは新しい組み込みの ワークグループの導入にも 取り組んでいます Swiftコミュニティに参加して swift.org/communityで さまざまな運営グループや ワークグループを確認してみてください Swift.orgは Swiftプロジェクトのホームです Webサイトワークグループは ホームページと スタートアップガイドに 大きな改善を加えました クロスプラットフォームライブラリや Webサービスなどの新しいチュートリアルが 多数含まれており Swiftの さまざまな技術の探索に役立ちます Swiftパッケージを確認するには swiftPackageIndex.comと統合されている swift.org/packagesに アクセスしてください Swift Package Indexは すべてのパッケージを 複数のSwiftバージョンや プラットフォームに対してビルドし アプリに最適なパッケージを 選ぶのに役立ちます Swiftコミュニティは毎月 Community Showcase向けに パッケージを推薦しています 推薦をご希望の場合は forums.swift.orgから お知らせください 今年のswift.orgブログ投稿では Swiftコミュニティ全体の 注目すべき発展に焦点を当てました 例をいくつか紹介します Browser Companyは Swiftの相互運用性を活かして ネイティブUIを使用した Windowsアプリを構築しました ブログ「Writing GNOME Apps with Swift」では 結果ビルダーがネイティブの GNOME UIライブラリのための 宣言型シンタックスを可能にした方法を 伝えています このブログ投稿は Swift 6の新機能 パックイテレーションについて述べています パックイテレーションは 値パラメータ パックとやり取りするプロセスを シンプルにするものです 例えば パックイテレーションを 使用すると 任意の長さのタプル等価演算子の 実装が簡単になります Swiftは より多くのプラットフォームに 移植されるにつれて クロスプラットフォーム言語として 成長し続けています SwiftはAppleプラットフォーム Linux Windowsで公式にサポートされています さらに Swiftコミュニティによって開発された 多数のプラットフォームが存在し それにはWebAssemblyも 含まれています
今年は サポート対象の Linuxプラットフォームが FedoraとDebianにまで 拡大されました
Xcodeは初めから Swiftの主要なIDEであり 今でも Appleプラットフォームでの アプリ開発に使用され続けています 一方 他にもさまざまな 開発環境が存在するため 私たちは Swiftをサポートする SourceKit LSPを開発しました これはSwiftのための言語サーバ実装であり IDEやエディタがSwiftを 統合できるようにするものです コミュニティの皆さんがSourceKit LSPを VSCode Neovim Emacsなどで 採用している姿を見るのは とてもエキサイティングです
これにより 任意のエディタと プラットフォームで はるかに簡単に 開発できる ようになっているはずです クロスコンパイルは 一般的な開発ユースケースであり Appleプラットフォーム向けに 開発を行っていれば すでにクロスコンパイルを 使用しているはずです クロスコンパイルでは ある環境で 実行可能ファイルを生成し 別の環境で実行することができます 例えば macOSでアプリをビルドし iPadで実行することができます 今後はこの機能をLinuxでも 提供したいと考えています つまり 馴染みのあるmacOS環境で開発し プログラムをLinuxサーバやコンテナに デプロイできるようになるということです
次に macOSからLinuxへの クロスコンパイルを支援する 完全に静的なLinux SDKを紹介します 静的リンクライブラリを使用すると プログラムを実行するために 追加のパッケージを インストールする必要がなくなります 実際にどう機能するか見てみましょう ここではシンプルなREST APIを持つ Swiftパッケージを使用します このAPIはランダムに1つの猫の顔の 絵文字を返します このパッケージについてさらに詳しく 知りたい場合は 「Meet Swift OpenAPI Generator」を チェックしてください このパッケージをmacOSでビルドし 静的Linux SDKを使用して Linuxサーバにデプロイします 今 3つのターミナルウィンドウを 開いています 左側のターミナルでは swiftパッケージをビルドします このターミナルはmacOSを実行している 私のローカルマシンにログインしています 右上のターミナルも私のローカル macOSマシンにログインしています その下のターミナルでは LinuxホストへのSSH接続が開かれています まず macOS用にサービスをビルドするため swift buildを実行します
生成されるバイナリは macOSでの実行用にビルドされており ビルド出力をチェックして 確認できます
このサービスをローカルマシンの 右上のターミナルで実行してみましょう
そして localhostでリッスンしている サーバにリクエストを送り ローカルサーバがリクエストを ログに記録するのを確認します
次に このサービスをクロスコンパイルして Linuxサーバで実行できるようにしましょう まず 完全に静的なLinux SDK for Swiftを インストールする必要があります
ではインストールの間に クロスコンパイルに 必要なフラグについて説明します swift-sdkフラグは どのSDKに対して ビルドするかを指定します ここでは ARM64 Linux環境用に コンパイルし muslにリンクするよう指定しています これにより どのLinuxマシンでも実行できる 静的リンクバイナリが生成されます Swiftランタイムがインストール されていないマシンでもかまいません swift buildコマンドにフラグを追加して ビルドを開始します
今回 生成されるバイナリは Linuxで実行されるようビルドされており ビルド出力をチェックして 確認できます
これをLinuxサーバにコピーして 実行しましょう
これで MacからLinuxサーバに リクエストを送ることができます
成功です 猫の顔の絵文字が返ってきました
まずmacOSでサービスを作成し macOSホストで実行しました 次に 完全に静的な Linux SDK for Swiftを使用して macOSからLinuxホストへの クロスコンパイルを行いました これにより 追加のランタイムを インストールせずに どのLinuxマシンでも実行できる 静的リンクバイナリを 生成することができました SDKのプレビュー版は swift.org/installからダウンロードできます それでは Swiftの主要なライブラリについて 見ていきましょう Foundationは多くのアプリの 重要なコンポーネントであり JSONのデコーディングや 日付と時刻のフォーマット ファイルシステムの操作などの 重要なAPIを提供しています また macOS Xの初期から存在する 最も長寿なフレームワークの1つでもあります Swiftがオープンソース化されたとき 私達はこのAPIがすべてのプラットフォームで 有用であることを知っていました そこで swift-corelibs-foundation プロジェクトを導入しました それ以来 言語は進化し 現在ではすべてのプラットフォームで 単一の統一された実装を 使用できるようになりました そのため私達はFoundationを書き直し レガシーのCおよびObjective-Cから 最新のポータブルなSwiftにしました その結果 一貫性と品質が上がっただけでなく パフォーマンスも向上しました 新機能や改良はSwift自体と同様 サポートされるすべてのプラットフォームに 同時に提供されます このSwift実装は昨秋 iOSとmacOSに初めて搭載されました Objective-Cアプリも これらの改良の恩恵を受けました さらに良いことに swift-foundationはオープンソースです Appleはコミュニティからの貢献を 歓迎しているだけでなく 新しいAPIの追加については オープンな進化プロセスを導入しています 例えば プレディケートは Swift 6でswift-foundationを通じて すべてのプラットフォームで利用可能な APIです 今年は正規表現も サポートするようになりました この新しい実装と コミュニティとの緊密な相互作用という 両面でのFoundationの新しい 方向性について とてもワクワクしています それでは 新しい フレームワークについて話していきましょう Swift Testingです これは親しみやすく 表現力豊かで 柔軟かつスケーラブルなものです マクロなどの最新のSwift機能を活用し 並行処理とシームレスに統合されています このパッケージはクロスプラットフォームを 念頭に オープンソースで開発されています XcodeやVSCodeなど複数のIDEと シームレスに統合するよう 設計されています Swift Testingライブラリのビジョンは エコシステムの公式かつ デフォルトのテストソリューションに なることです この包括的なAPIについて詳しくは Swiftの進化のビジョンに関する ドキュメントを参照してください では Swift Testingのいくつかの 機能を見ていきましょう テストを宣言するには 関数にTest属性を追加します Test属性の引数として カスタム表示名を指定することができます それにより テストで何をしているのかを 理解しやすくなります expectを使うと結果を 検証することができます これはマクロであり シンプルまたは 複雑なSwift表現を記述できます Swift Testingでは タグを使ってテストを 整理およびフィルタすることができます 引数を使うと 複数の入力に対して 同じテストを繰り返さないようにできます こちらは Swift Testingの 機能の一部をハイライトしたものです 詳しくは 「Meet Swift Testing」と 「Go further with Swift Testing」を チェックしてください コードはテストする前に ビルドする必要がありますので Xcodeでのコードのビルド方法についても 改良を加えました Swiftコードをビルドする時 各モジュールは他のモジュールに依存します 多くの場合 SDKからのモジュールです Swiftコンパイラは SwiftUIのようなモジュールに対して そのモジュールのバイナリ版を ビルドする必要があります これは暗黙的に行われるため 一度きりの遅延としてしか 認識されないかもしれません しかし 実際は多くの作業が隠れています Objective-CやC++で書かれたものを含む すべてのモジュールを 順次ビルドしなければならないからです 別のSwiftモジュールがビルドされる際は 同じバイナリモジュールが再利用されますが それらが準備できるまで待たなければ ならないことがあり その結果 ビルドから得られる 並行性が限定されます さらに デバッガでこれらのモジュールファイルの 独自バージョンのビルドが 必要になる場合があるため デバッガで最初に変数を表示する際 長い待ち時間が発生する可能性があります 明示的にビルドされたモジュールは こうした暗黙のステップを 明示的なビルドステップに変えます その結果 ビルドが並行して実行され ビルドログに明確に 表示されるようになります 結果として より予測可能で 信頼性の高いビルドが実現します デバッガはビルドとバイナリモジュールを 共有できるようになり デバッグが高速になります
明示的なモジュールビルドは Xcodeのビルド設定で有効にできます Demystify explicitly built modules」 で詳細をご確認ください
過去10年間で Swiftは大きく成長しました 新しい仲間が増え 独自の経験を積んできましたが いよいよ自分自身の空間に移行する時が 来ました Swiftは新しい組織 github.com/swiftlangに移行します そしてSwiftプロジェクトによって 管理されるようになります これには Swiftコンパイラ Foundation および多くのSwiftエコシステムの パッケージが含まれます 移行はまもなく開始され 詳細がswift.orgに掲載されます Swiftが新しいスペースで 成長することを楽しみにしています 言語とエコシステムの進化にご協力いただき ありがとうございます しかし これはほんの始まりに すぎません ここからは Meghanaから Swift 6の新しく素晴らしい 言語機能について説明してもらいます 今年はSwiftにとって素晴らしい年でした Swift 6は データレースの安全性を実現する 新しい言語モードを導入し Swiftの安全性保証を 並行プログラムに拡張しています また Embedded Swiftという 新しい言語サブセットも導入し 制限の厳しいシステムでも動作します 加えて Swift 6には数多くの 新しい改善点が組み込まれ Swiftがさらに良いものになっています まず コピー不可の型について 見ていきましょう すべてのSwift型は 値型でも参照型でも デフォルトでコピー可能です コピー不可の型は このデフォルトのコピー可能性を制限します それにより 固有の所有権を表す シナリオに適しています 例えば ファイルのような 固有のシステムリソースは コピー不可の構造体として 表現することができ デイニシャライザによって 自動的に閉じられます この表現により 複数の人が 同じファイルに書き込むような ランタイムの問題を防ぐことができます また 自動クリーンアップがない場合に 発生しがちな リソースリークも防止できます ただ この表現は まだ理想的なものとはいえません イニシャライザは開かれたファイル記述子を 受け取りますが これは直感的でない上に 安全でもありません
ファイルを開いて初期化するまでの間に コードを追加することで プログラムが終了する可能性があり デイニシャライザが実行されず リソースリークが発生します これを修正するには ファイル名を引数とする 失敗可能なイニシャライザを使用して ファイルを開き ファイル名が有効であれば 初期化を完了するようにします このイニシャライザはコピー不可の ファイル型のOptionalを返します Optionalは標準ライブラリの ジェネリック型です Swift 5.10でのコピー不可の型の サポートは具体的な型に限られていました Swift 6では すべての ジェネリックコンテキストで コピー不可の型が サポートされるようになりました またOptionalのような 標準ライブラリの 重要なジェネリック型にも対応しています そのため ファイル型のようなコピー不可の型の 失敗可能なイニシャライザを 記述できるようになりました コピー可能型とコピー不可型の 両方に対して 抽象化できる パワフルな機能によって コピー不可の型の 使用の可能性が拡大します 詳しくは「Consume noncopyable types in Swift」をご確認ください コピー不可の型は 固有の所有権を表現するだけでなく パフォーマンスに対する 詳細なコントロールも可能にします リソース制限の厳しい 低レベルシステムでは コピーがコスト高になる可能性があり ここでもコピー不可の型が適しています 低レベルシステムはメモリや ストレージ ランタイム機能に制限があります そうしたシステムではCおよびC++が 低フットプリントのため プログラミングの 主な選択肢となっていましたが 今ではSwiftも使用できます Embedded Swiftは Swiftの新しい言語 サブセットおよびコンパイルモデルであり 非常に小さなスタンドアロンバイナリを 生成できます これは制限の厳しいシステムに適しています ランタイムサポートが必要な リフレクションやAny型などの 特定の言語機能はオフになり 完全なジェネリック特殊化や 静的リンクなどの コンパイラ技術を使用して 適切なバイナリが生成されます 一部の言語機能をオフにしても Embedded Swiftサブセットは「完全な」 Swiftに非常に近いものに感じられ わかりやすく 読みやすいSwiftコードを 簡単に書き続けることができます
Embedded Swiftがあれば Swiftで書かれたゲームが Playdateのようなコンパクトな ゲームコンソールで機能します バイナリサイズが わずか数キロバイトのゲームです しかし Embedded Swiftは遊びや ゲームのためだけのものではありません 産業アプリケーションの構築に人気のある さまざまなARMやRISC-Vの マイクロコントローラで使用できます AppleのSecure Enclaveプロセッサは Embedded Swiftを使用しています Secure Enclaveは メインプロセッサとは別の 独立したサブシステムで 機密データを保護することに 特化して使用されています
そのようなシステムでは セキュリティが極めて重要で Embedded SwiftはSwiftの 安全性保証を提供しています Swiftは CおよびC++との 相互運用性を備えているため 組み込みプロジェクトで Swiftを段階的に導入することができます 「Go small with Embedded Swift」 で詳細をご確認ください
昨年には C++との双方向の 相互運用性を組み込みました SwiftはC++と直接相互運用が可能で シームレスなデベロッパ体験を提供し ブリッジコストもかかりません Appleは相互運用可能な言語機能を 引き続き拡張しており Swift 6では C++の仮想メソッド デフォルト引数 ムーブオンリー型 および重要なC++標準ライブラリ型を Swiftに直接インポートできます ここでの相互運用性とは 類似の言語概念をマッピングし セマンティクスに合わせて 調整を行うことをいいます C++の仮想メソッド およびデフォルト引数は 対応するSwiftバージョンに マッピングされます Person型のような C++のムーブオンリー型は Swiftでは コピー不可の型にマップされます Swiftコンパイラは 必要に応じてC++のムーブコンストラクタの 呼び出しを挿入します もし意図せずコピー不可の値を コピーしようとした場合は Swiftコンパイラが それを診断してくれます C++は広く使われている プログラミング言語ですが 安全性保証が欠けているため セキュリティ攻撃の対象になりがちです C++プロジェクトで Swiftを段階的に採用することで セキュリティと生産性を高めることができます Macでは FinderがC++の 相互運用性を使用するようになりました ブラウザメーカーはこれを使って WindowsでARCブラウザを立ち上げます Swift GodotはGodotゲームエンジンへの Swiftバインドのために使用されます C++は大規模な言語であり その相互運用性は進化し続けています 最新情報はswift.orgでご確認ください C++の相互運用性について さらに詳しくは 昨年の 「Mix Swift and C++」をご覧ください Swiftは例外的な条件に遭遇した際に エラーをスローし 伝達してキャッチするための 第一級の エラーハンドリングサポートを備えています エラーがerrorプロトコルに 準拠していれば throwsキーワードを使って スローする関数を記述できます スローされたエラーは型が消去され 任意のError型として catchハンドラに表示されます 型の消去により エラーの具体的な 型情報が失われるため まれにエラーを 完全に処理したい場合などは 動的型チェックを 挿入する必要があるかもしれません 型消去にはboxing/unboxingが伴います ランタイムの割り当て機能がない 制限の厳しいシステムでは これが課題になります Swift 6はこの問題を克服するために 型指定されたthrowを導入しました 型指定されたthrowでは throwsキーワードとともに エラー型を指定できます 型消去は行われず エラーはキャッチブロックで 具体的な型で示されます 型指定されたthrowは 現在のエラー ハンドリングシステムを一般化したものです 型指定なしthrowは Any型のエラーを持つ 型指定されたthrowと同等です そして例外をスローしない関数は Never型の型指定されたthrowと同等です 型指定されたthrowによって 導入されたこの定式化により エラー型をジェネリックに 処理することができます 例えば map関数はスローする可能性のある クロージャを受け取り その要素に対してクロージャを マッピングします 型指定されたthrowを使用すると map関数は Failure型に対してジェネリックに記述され スローする場合としない場合の 両方を抽象化できます これにより コードの重複を避け 正確なAPI契約を定義できます 型指定されたthrowはAPI契約で 失敗型を指定するため API進化を制限します スローされるエラー型を変更できる 柔軟性を保ちたい場合は 型指定なしthrowを 継続して使用してください 内部関数を使用する場合や 引数からエラーをプロパゲートする関数を 使用する場合 または制約環境で作業する場合は 型指定されたthrowを使用してください そうした場合は 型指定なしthrowの コスト効率が低くなるためです
型指定されたthrowと すでに説明したその他の新機能に加えて Swift 6コンパイラには 言語に関する種々の強化機能と パフォーマンスや堅牢性に関する さまざまな強化機能が組み込まれています さらにそれだけでなく Swift 6コンパイラには 新しいSwift 6言語モードも追加されました このモードはデータ競合に対する 安全性をデフォルトで実現するものです データ競合は 並行プログラムを書く際に 一般的に発生するプログラムエラーです 複数のスレッドがデータを共有している際に そのうちの1つが データを変更しようとすると発生します データ競合は予期しないランタイム動作や プログラムのクラッシュ 再現が難しい 問題などを引き起こす可能性があります Swiftの並行処理は 当初からデータ競合の安全性を 主な目標としており 私たちはその目標に向けて 段階的に進歩してきました Swiftの並行処理は データ分離を 実現するメカニズム 可変状態を 保護するアクター 安全なデータ共有のための Sendableに基づいて設計されました Swift 5.10は 完全な並行性チェックフラグで データ競合の安全性を実現しましたが 新しく導入された Swift 6言語モードは デフォルトでデータ競合の安全性を確保します これにより アプリ内のすべてのデータ競合の 問題が コンパイル時エラーになります アプリのセキュリティが大きく向上し デバッグの時間も大幅に減少します 新しい言語モードでは コードの調整が必要な場合があるため 準備が整ったタイミングで 採用してください これはモジュールごとに採用することができ 依存関係も Swift 6言語モードに 移行済みかどうかに関わらず相互運用できます データ競合の安全性は Swift 6言語モードを有効にする ことによってのみ更新されます その他の更新はすべて デフォルトで利用できます Swift 6コンパイラにアップデートするだけです さらに データ競合チェックも 大幅に改善しました 安全性を確保するため Swift 5.10の完全な並行性チェックでは 非Sendable値をアクターの 隔離境界を越えて渡すことを禁止しました Swift 6は 元の隔離境界から 参照されなくなるシナリオでは 非Sendable値を渡すことが 安全であると認識します 例えば 非Sendableな クライアント参照を MainActorから ClientStoreアクターに渡すと Swift 5.10の完全な並行性チェックでは コンパイラ警告が表示されます しかし クライアント参照は ClientStoreアクターに送信された後は MainActorから参照されなくなります MainActorと ClientStoreアクターの間で クライアントの状態が共有されていないため データ競合は発生しません Swift 6の データ競合チェックの強化により これは正常にコンパイルされます また ClientStoreActorに クライアント参照を渡した後に クライアント参照を導入すると コンパイラは データ競合を示すエラーを発生させます アクターによって提供される 高レベルの同期モデルに加えて Swift 6にはいくつかの新しい 低レベルのプリミティブが含まれています Synchronizationモジュールは Atomicsを導入します Atomicsは プラットフォーム上で 効率的なロックフリー実装を提供する 任意の型に対してジェネリックです Atomic値は安全な並行アクセスのため 常に「let」プロパティに 格納する必要があります アトミックに対する操作は すべて明示的であり CおよびC++のメモリモデルに類似した メモリオーダリング引数を持ちます Synchronizationモジュールには Mutexも導入されています Atomicsと同様に Mutexも「let」プロパティに格納し 安全に並行してアクセスすることができます Mutexによって保護されている ストレージへのすべてのアクセスは withLockメソッドに渡された クロージャを介して行われ 相互排他アクセスを確保します
段階的な移行のためのインフラストラクチャ データ競合チェックの改善 そして新しい低レベルの 同期プリミティブにより データ競合の安全性を確保するために 必要なすべてのツールが揃いました 移行のベストプラクティスは 「Migrate your app to Swift 6」の ハンズオンチュートリアルを 参照してください 今日は新しく改良された言語機能 価値ある安全保証 そしてSwiftの新たな展望について いろいろと説明してきました ぜひswift.orgにご参加ください Swiftの次の10年を 一緒に形作っていきましょう ご視聴ありがとうございました 良いコーディングを!
-
-
9:15 - Swift Build
swift build
-
9:20 - Inspecting the build output
file .build/debug/CatService
-
9:24 - Run the REST API service
.build/debug/CatService
-
9:30 - Make a request to REST API service
curl localhost:8080/api/emoji
-
9:45 - Install the Fully static Linux SDK for Swift
swift sdk install ~/preview-static-swift-linux-0.0.1.tar.gz
-
10:18 - Swift build command flag to cross compile
swift build --swift-sdk aarch64-swift-linux-musl
-
10:30 - Inspecting the build output
file .build/debug/CatService
-
10:35 - Copy the service over to our Linux server and run it
scp .build/debug/CatService demo-linux-host:~/CatService ./CatService
-
10:45 - Make a request to REST API service from macOS to Linux
curl demo-linux-host:8080/api/emoji
-
13:50 - Swift Testing - Declare a test function
// Swift Testing import Testing @Test func rating() { let video = Video(id: 2, name: "Mystery Creek") #expect(video.rating == "⭐️⭐️⭐️⭐️") }
-
13:55 - Swift Testing - Customize a test’s name
// Swift Testing import Testing @Test("Recognized rating") func rating() { let video = Video(id: 2, name: "Mystery Creek") #expect(video.rating == "⭐️⭐️⭐️⭐️") }
-
14:13 - Swift Testing - Organize test function with tags
// Swift Testing import Testing @Test("Recognized rating", .tags(.critical)) func rating() { let video = Video(id: 2, name: "Mystery Creek") #expect(video.rating == "⭐️⭐️⭐️⭐️") }
-
14:19 - Swift Testing - Parameterize test with arguments
// Swift Testing import Testing @Test("Recognized rating", .tags(.critical), arguments: [ (1, "A Beach", "⭐️⭐️⭐️⭐️⭐️"), (2, "Mystery Creek", "⭐️⭐️⭐️⭐️"), ]) func rating(videoId: Int, videoName: String, expectedRating: String) { let video = Video(id: videoId, name: videoName) #expect(video.rating == expectedRating) }
-
17:50 - Noncopyable types
struct File: ~Copyable { private let fd: CInt init(descriptor: CInt) { self.fd = descriptor } func write(buffer: [UInt8]) { // ... } deinit { close(fd) } }
-
18:12 - Noncopyable types
guard let fd = open(name) else { return } let file = File(descriptor: fd) file.write(buffer: data)
-
18:42 - Noncopyable types
struct File: ~Copyable { private let fd: CInt init?(name: String) { guard let fd = open(name) else { return nil } self.fd = fd } func write(buffer: [UInt8]) { // ... } deinit { close(fd) } }
-
22:29 - C++ Interoperability
struct Person { Person(const Person&) = delete; Person(Person &&) = default; // ... };
-
22:34 - C++ Interoperability
struct Developer: ~Copyable { let person: Person init(person: consuming Person) { self.person = person } } let person = Person() let developer = Developer(person: person)
-
22:40 - C++ Interoperability
struct Developer: ~Copyable { let person: Person init(person: consuming Person) { self.person = person } } let person = Person() let developer = Developer(person: person) person.printInfo()
-
23:43 - Untyped throws
enum IntegerParseError: Error { case nonDigitCharacter(String, index: String.Index) } func parse(string: String) throws -> Int { for index in string.indices { // ... throw IntegerParseError.nonDigitCharacter(string, index: index) } } do { let value = try parse(string: "1+234") } catch let error as IntegerParseError { // ... } catch { // error is 'any Error' }
-
24:19 - Typed throws
enum IntegerParseError: Error { case nonDigitCharacter(String, index: String.Index) } func parse(string: String) throws(IntegerParseError) -> Int { for index in string.indices { // ... throw IntegerParseError.nonDigitCharacter(string, index: index) } } do { let value = try parse(string: "1+234") } catch { // error is 'IntegerParseError' }
-
24:39 - Typed throws - any and Never error types
func parse(string: String) throws -> Int { //... } func parse(string: String) throws(any Error) -> Int { //... } func parse(string: String) -> Int { //... } func parse(string: String) throws(Never) -> Int { //... }
-
28:02 - Passing a NonSendable reference across actor isolation boundaries
class Client { init(name: String, balance: Double) {} } actor ClientStore { static let shared = ClientStore() private var clients: [Client] = [] func addClient(_ client: Client) { clients.append(client) } } @MainActor func openAccount(name: String, balance: Double) async { let client = Client(name: name, balance: balance) await ClientStore.shared.addClient(client) }
-
28:52 - Atomic
import Dispatch import Synchronization let counter = Atomic<Int>(0) DispatchQueue.concurrentPerform(iterations: 10) { _ in for _ in 0 ..< 1_000_000 { counter.wrappingAdd(1, ordering: .relaxed) } } print(counter.load(ordering: .relaxed))
-
29:21 - Mutex
import Synchronization final class LockingResourceManager: Sendable { let cache = Mutex<[String: Resource]>([:]) func save(_ resource: Resource, as key: String) { cache.withLock { $0[key] = resource } } }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。