ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
SwiftパッケージをXcodeに導入する
コードの整理と共有に便利なSwiftパッケージが、すべてのAppleプラットフォーム向けのAppをXcode 11で構築する際に利用できるようになりました。このセッションでは、コミュニティで開発されたパッケージをプロジェクトで使用する方法、Swiftパッケージの構造、パッケージのバージョン管理と依存関係の仕組みについて説明します。
リソース
関連ビデオ
WWDC22
WWDC21
WWDC20
WWDC19
-
ダウンロード
(音楽)
(拍手) こんにちは Xcodeエンジニアのアンダースです 今回は同僚のバルラージと一緒に Swiftパッケージについてご説明します
オープンソースツールである Swift Package Managerは Swift 3で登場しました その後 多くのSwiftパッケージが 作成されています 他のパッケージマネージャ向けに 書かれたオープンソースライブラリも 多くがSwift Package Managerと 互換性を持ちます
Swiftパッケージでは― 依存関係のバージョンや バグ修正の管理ができます パッケージをアップデートすれば コードも壊さずに済みます またアプリケーション間で コードを共有する際にも便利です 開発を行う小さなチームや 大きな組織― または個人のデベロッパの皆さんにも お使いいただけます
Xcode 11ではSwiftパッケージに プロジェクトから直接アクセスできます
(拍手) うれしいですよね
まずはパッケージを使って― どのようにアプリケーションの機能を 拡張するのかをお話しします 次に構成やファイルフォーマットなど パッケージの詳細についてご紹介します 適切なバージョンのパッケージを どう取得するかなど パッケージ解決の詳細にも触れます パッケージの アップデートに関するお話では 公開された新バージョンを どう活用するかご説明します そしてアップデート時に起き得る バージョン競合の解決法にも触れます
まずはNAP機能を拡張し パッケージを活用してみましょう
このシンプルな iPhoneアプリケーションは 職場の近くにあるカフェの ランチメニューを表示しています 見出しが2つありますね SwiftUIを使えばアプリケーションを 起動せずにXcodeでプレビューできます
2つの店のランチメニューが 表示されています 実際のアプリケーションでは ネットワークからデータを取得しますが このデモ版では ローカルファイルのデータを使います つまりメニューのソースはローカルです (笑い声) この2つのJSONファイルも 問題ありませんが もう1つのカフェはより高級なので メニューはYAMLにしました そちらが表示されていないので データをロードする ソースコードを見てみましょう JSONは扱っているのに YAMLを扱っていません YAMLを解析できるライブラリと Swiftインターフェイスを装備 早速その“Yams”を使ってみましょう “File”メニューをクリックし “Swift Packages”から “Add Package Dependency”を選びます 他のパッケージが追加されれば 他のサブメニューも使用可能となります
ここでは“Add Package Dependency”を選びます Xcodeの“Preferences”に 追加したGitHubアカウントで パッケージのリポジトリが確認できます 星を付けた他のリポジトリも見えます “Yams”には星を付けました 上部にはパッケージのURLを 入力することも可能です
今回は“README”をクリックし “Yams”のページへ いいですね このAPIの内容を見てみると 今回はこれが使えそうです オープンソースライブラリであっても 他人が書いたものなので 出所が信頼できるかどうかを 十分に確認してください 何のライブラリなのか 理解することも大切です アプリケーションのライセンスと 互換性があるかも確認してください
確認できたらXcodeに戻り “Next”をクリックして リファレンスと依存関係を Yamsに追加します
使用可能なバージョンが確認でき 最新のものが自動でセットされます これらのオプションの詳細は 後ほどお話しします 大抵の場合は デフォルトのものが最適です バージョン2.0以上を使用しますが 次のメジャーバージョンは含みません
“Next”をクリック XcodeがYamsのコンテンツを取得します
パッケージによっては 複数のプロダクトを持ちます 今回はパッケージと 同名のライブラリです 複数あればリンクしたいものを選択 今回は“Lunch”を選びます
そして“Finish”
XcodeがYamsのパッケージ依存関係に リファレンスを追加しました “Swift Packages”タブで確認できます
またYamsパッケージが“Swift Package Dependencies”のセクションにあります
このパッケージについては 後ほど見ていきます まずは“FoodMenu”を開き コードからパッケージを 使えるようにします “import Yams”と記述します コード補完機能もあります またimport文をCommandクリックすると 定義に移動します ここではレンダリングされた インターフェイスのドキュメントを 確認することができます これらはパッケージに含まれる ドキュメントコメントから来ています
コードに戻りcase文を加えます
“case "yaml":”
そして“YAMLDecoder”のみ記述します ライブラリの全メソッドが コード補完され クイックヘルプも見られます 得られるサポートのクオリティは ビルトインAPIに匹敵します 1つ目の値には “case "json":”と同じものを使います 2つ目は“Data”の代わりに “String”を使います デフォルト値を使うので 3つ目の値は不要です
新モジュールをインポートしたので リストのビューを再確認します “Resume”を押すとアプリケーションが バックグラウンドで再ビルドされます YAMLデータファイルのコンテンツも表示 (拍手) これをリポジトリにコミットしましょう
予想どおりにソースが変更されています 拡大しましょう Commit Sheet上でも ソースが変更されています リファレンスを追加したので― プロジェクトファイルも 変更されています またXcodeはSwift Package Managerに “swiftpm”というディレクトリを作成 “shareddata”の下です 内容は後ほど説明するので チェックを入れます 解決されたバージョンの情報は保存され チェックを入れれば 同じバージョンを共有できます
チェックを入れたので次は― “YAMLメニューを使用”と 書いておきます
ではスライドに戻ります
オープンソースパッケージの使い方を 紹介しました 次はYamsパッケージを 詳しく見ていきましょう
それはSwiftパッケージの マニフェストを含むディレクトリです “Package.swift”がディレクトリを Swiftパッケージと定義します またソースや その動きをテストする ユニットテストも含みます
ソースの下にあるのは ターゲットごとのサブディレクトリです コンポーネントは個別にビルド可能 “Test”の下には各テストスイートの サブディレクトリがあります
ターゲットディレクトリの中身を見ます 各ターゲットはCベースの言語 またはSwiftでの実装が可能です YAMLの場合はC言語で書かれた CYamlのパーサがあります またObjective-C++ファイルを 含むこともあります 別のターゲットには Swiftインターフェイスもあり CYamlコードを呼び出します
ユニットテストは Swiftで書かれています
Swiftパッケージの マニフェストを見てみましょう 1行目はパッケージに必要な ツールのバージョンを宣言 マニフェストをパースできる 最低限のバージョンを示しています
パッケージ説明のAPIは宣言型APIで “PackageDescription”ライブラリが 提供します これをインポートすることで ファイル内の他のコンテンツが パッケージの特性を宣言できます
パッケージの名前も含まれます またパッケージがクライアントに渡す プロダクトも掲載 クライアントがインポートできる コードを制御します 今回はパッケージと 同名のライブラリ“Yams”です また後ほどご説明しますが “targets:…”が意味するのは このライブラリがターゲット“Yams”を ライブラリとして公開することです
“targets”のセクションが示すのは 個別にビルドできるもので このとおり ソースフォルダと ターゲットが1対1で対応しています 各ソースフォルダは サブフォルダも持てますが 最上位フォルダは 各ターゲットにつき1つです
この例ではターゲット“CYaml”は 依存関係を持ちません 依存関係を持つのは ターゲット“CYaml”です プロダクトがYamsを参照すると 間接的にCYamlも取り込みます
ユニットテストの テストターゲットが1つあります クライアントにはリンクしませんが ライブラリの正常な動作のためには 必須のコードです
今回Yamsパッケージのマニフェストは 互換性を持つ Swiftの旧バージョンも示しています 他にもこの宣言型言語の中で 述べられる特性はありますが それはまた後ほど
では起動したアプリケーションに リンクしてみます プロジェクトは ソースファイルで構成され 言語はSwiftか別のものです 依存するパッケージも ソースファイルです Xcodeはこれらすべての ソースファイルをコンパイルします 特にアプリケーションのコードと 互換性を持つように パッケージコードをコンパイルします アーキテクチャや プラットフォームなどが含まれます アプリケーションが必要なものに応じ 再コンパイルを複数回行います そしてリンクし すべてを アプリケーションにまとめます ライブラリはデフォルトでは静的なので 全コードがリンク
同じパッケージを使う アプリケーション向けに繰り返されます iOSでもwatchOSでも 同じパッケージを使います 各アプリケーションのために Xcodeは何度もコードをビルドします
パッケージに依存する プロジェクトについてでした ターゲットエディタで パッケージ依存関係が確認できましたね しかしパッケージはマニフェストを通し 別のパッケージにも依存できます パッケージマニフェストでYamsに 依存関係のセクションがなかったのは 他のパッケージに 依存していないからです しかしパッケージ依存関係グラフは 間接依存関係も含みます
Package Managerで バージョンの管理ができます セマンティックバージョニングは バージョンの3つのパートに 意味を持たせる方法です 広く使われています
例えば― メジャーバージョンが上がるのは APIに破壊的変更があった時です つまりクライアント側の変更が 必要となる場合です 例えばメソッドの名前変更や消去 またはクライアント側の適応も 求められるような 意味的に重要な変更が加えられた時です バージョン制限で― 次のメジャーバージョンを 含まなかったのは そのためです
マイナーバージョンが上がるのは クライアントを破壊しない形で 機能追加が行われた時です メソッドの追加などですね
パッチバージョンが上がるのは 意味的に重要ではない形で バグ修正が行われた時です パッケージがバグ修正のために アップデートしても 意味的な変更なしに バグ修正を取り込めます
パッケージの使い方や 詳細を見てきました ここでバルラージを呼び パッケージ解決について 説明してもらいましょう (拍手) アンダース ありがとう パッケージ解決とは パッケージバージョンを選ぶ際に Xcodeが行うプロセスです これがどのように働くのか 見ていきましょう 先ほどのLunchプロジェクトを使って ご説明します
“Swift Packages”タブの プロジェクトエディタでは LunchがYamsに 依存していることが分かります バージョンルールは2以上で 次のメジャーバージョン未満 つまりバージョン2以上ですが バージョン3は含みません
プロジェクトナビゲータ内の “Swift Package Dependencies”には バージョン2.0のYamsが確認できます 詳しく見ていきましょう
要求はバージョン2以上なので バージョン2.0のYamsが選ばれます もしバージョン2.1があれば そちらが選ばれていました ルール内の最新バージョンだからです しかしバージョン3があっても それは選ばれません 設定した制限に引っかかるからです この2.1や3は仮定に基づく例です 今回のセッションでは Yamsはバージョン2で解決を行います
今回 選べるパッケージの バージョンは1つですが もう少し複雑なパッケージ解決の ケースを見ていきましょう
こちらがアプリケーションのLunchです ベーシックなUIで 使っているパッケージも1つです
私のチームはアプリケーションに 複数のパッケージを追加しました 共通のデザインテーマを 持たせるためです そしてその数週間後 Lunchの作業に戻ると― UIがアップデートされ 3つのパッケージが追加されていました “DesignFont”“DesignTheme” “DesignColor”の3つです それぞれのバージョンで解決されます
Xcodeはこれらのパッケージの バージョンを選んでくれました ではなぜこれらのバージョンで パッケージが解決するのでしょう それを知るために プロジェクトエディタに戻ります
Swiftパッケージの依存関係に “DesignTheme”が加わっています ルールは1以上 次のメジャーバージョン未満
今回 Xcodeはバージョン1の DesignThemeを選びました 1から次のメジャーバージョンまでで 解決するからです
Yamsとの依存関係に変化はありません “DesignFont”と“DesignColor”の 場所が気になりますね プロジェクトエディタ内にはありません これはプロジェクトエディタが Lunchと直接依存関係を持つ パッケージを示すからです
ではパッケージの依存関係を 確認するために DesignThemeパッケージを 見てみましょう 直近で追加されたものです またYamsからの 依存関係ではないと考えられます では“Swift Package Dependencies”の 下にあるものを 簡略化して見ていきましょう “DesignTheme”がありますね
パッケージを開くと コンテンツが現れます 今回はマニフェストファイルである “Package.swift”を確認します
このパッケージの依存関係の情報が 含まれているからです ファイルを開くと依存関係の配列に “DesignFont”と“DesignColor” そしてバージョン要求が確認できます
バージョンルールに従って DesignFontが解決されています なのでXcodeはパッケージの 最新バージョンである1.2を選びます
DesignColorの解決は少々異なり 1以上 次のマイナーバージョン未満 つまりDesignColorの バージョンは1以上ですが バージョン1.1は含みません これはパッケージが アップデート時に取得するバージョンに やや慎重になりたい時に使われます XcodeはDesignColorの バージョン1.0.1を選択しました これらのバージョンで解決された経緯が この全体像から分かります
アンダースが行ったデモの最後には Yamsをインポートしています パッケージ解決に関わるからです
すべてのパッケージは 同名のライブラリを生成します
LunchはDesignThemeとYamsから コンテンツをインポートしています
そしてDesignThemeは DesignFontとDesignColorから コンテンツをインポートしています
このグラフを見ると パッケージ解決とよく似ていますが これは意図的なものです パッケージに 直接依存関係を追加すると― そのコンテンツもアプリケーションの APIを使ってインポートされます しかしサブ依存関係のコンテンツを インポートしたい場合はどうでしょう その方法をご説明します
Lunchプロジェクトは DesignThemeに依存し DesignThemeは DesignFontに依存しています DesignFontは 同名のライブラリを生成します このコンテキストでLunchは すぐにDesignFontからコンテンツを インポートする必要はありません もしDesignThemeが DesignFontへの依存を失えば XcodeがDesignFontへの リファレンスを失うからです DesignFontライブラリも 使えなくなります 最初に戻り より良いアプローチをご紹介します LunchとDesignFontの間に 直接依存関係を設定した後 DesignFontのコンテンツを Lunchにインポート アップデートによりDesignThemeが DesignFontとの依存関係を失っても Xcode内にそのライブラリへの リファレンスを持ち続けられます
Xcodeはこのように パッケージのバージョンを選びます 次にお話しするのは― APIの改善やバグ修正を行う 新バージョンの取得方法についてです
DesignFontの管理チームと ランチをする機会があり バグ修正を施した 新バージョンの話を聞きました バージョン1.2.1です
確認すると DesignFontはバージョン1.2です つまりLunchプロジェクトは バージョン1.2を使っています
ですので このパッケージを アップデートします “File”から“Swift Packages” Swiftパッケージに関する 複数のオプションが現れました 今回は最新バージョンに アップデートします 一番下をクリックして開始します
DesignFontのバージョンが 1.2.1になりました
ではこのアップデート作業では 一体どんなことが行われたのでしょうか
“Package.resolved”という ファイルがあります これはワークスペースの全パッケージの バージョン情報を記録します アップデート作業時には このファイルもアップデートされ Xcodeは新バージョンを選択します
ファイルはソースコントロールにおいて チーム内で共有することが多い― “xcshareddata”にあります 大事なのは先ほどのアップデート作業は ローカル作業だということです アップデートを共有するには Package.resolvedに 変更をコミットしてプッシュします
Xcodeのプロジェクトファイル内で すべてを確認できますが Package.resolvedを ご自身で編集する必要はありません Xcodeが代わりに行ってくれます
それではこのアップデートを チームと共有しましょう Xcodeの“Source Control”から “Commit”を選択します
Package.resolvedに加えた変更を 確認できます 変更前のバージョン1.2から 新たな1.2.1に どうアップデートしたのかも分かります これをプッシュしたいので“Push to remote”にチェックを入れます 変更をコミットしプッシュできます これでアップデートを チーム内で共有できました ではなぜPackage.resolvedファイルが 必要なのでしょうか
このファイルが存在するのには 理由があります Lunchの作業を行うチームの全員が 同じコミットで同じDesignFontの バージョンを取得するためです このファイルがないと問題が生じます チームの複数人が同じバージョンの プロジェクトに取りかかっているのに 使うパッケージのバージョンに 一貫性がないのです
ですからPackage.resolvedの確認は 非常に大事です でないとチームで使うパッケージの バージョンがバラバラになります 必ず確認してください
またパッケージの新バージョンも 常に意識し アップデートを行ってください 大事なバグ修正やAPIの改善を 逃してしまうかもしれません
以上がアップデートについてです 次はパッケージ競合の解決について 見ていきましょう 今日お話ししてきたトピックが 多く絡んできます
Lunchアプリケーション内の― 価格表示に使うフォントを変更する プロジェクトをローンチします
使いたいシステムフォントは DesignFontバージョン2のものです チーム内の他のアプリケーションが使う フォントのバージョンとも 一貫性を保ちます では変更しましょう DesignFontパッケージを使うには LunchとDesignFontの間に 直接依存関係を設定します 新フォントをリリースした バージョン2を 指定して使います
ではパッケージの追加を行いましょう お気に入りにある“DesignFont”を選び “Next”をクリック アップデートや新バージョンも 取得したいので 選ぶのは2以上で 次のメジャーバージョン未満です そして“Next” パッケージ解決エラーが出ました 2以上で 次のメジャーバージョン未満とした― 新たな依存関係要求が原因です
何が起きたのかを確認し デバッグしましょう パッケージ解決のデバッグを行う際は 全体像に目を向けてください パッケージに関する すべての要求を考慮します 最近追加したものとは限りません
少し前の段階に戻ります Lunchが直接依存関係を持っていた DesignThemeバージョン1は DesignFontバージョン1.2.1に 直接依存関係を持っていました バージョン要求は1以上で 次のメジャーバージョン未満です
その後LunchとDesignFontの間に 直接依存関係を追加し 2以上で次のメジャーバージョン未満と したところ競合が起こりました
DesignFontに対する DesignThemeの要求は 1以上ですが2を含みません DesignFontに対するLunchの要求は 2以上ですが3を含みません 両方の要求を満たすバージョンは 選択不可能です Swift Package Managerの Xcodeへの統合においては ワークスペースに持てる パッケージバージョンは1つです それがこのエラーの 理由にもなっています 両方の要求を満たすバージョンを 1つ選ぶことは不可能です 非常に特定しやすいエラーです しかし通常 このようなエラーに遭遇した場合 より新しいパッケージバージョンを 確認します そしてサブ依存関係へのアップデートを 提供したものがないかを見ます 今回のケースではDesignThemeの バージョン2をまだよく見ていません そこでGitHubでDesignThemeの バージョン要求を確認します
Swiftパッケージのマニフェストの 依存関係の配列が確認できます ここでDesignFontのバージョン要求が 1以上から2以上にアップデートされて いることがわかります これはLunchとDesignFontの間に 加えようとしていた要求を満たします DesignThemeの要求をバージョン2で 解決するようにアップデートできれば 問題なくLunchとDesignFontの間に 直接依存関係を追加できます
ですのでDesignThemeの メジャーバージョンを アップデートします Lunchは1以上の DesignThemeを使っていましたが 2以上で 次のメジャーバージョン未満とします
Xcodeに戻り― プロジェクトエディタ内の “DesignTheme”をクリックします バージョンルールが編集できます 1以上で次のメジャーバージョン未満を 2以上で 次のメジャーバージョン未満にします “1”を“2”に変えたら “Done”をクリック アップデート作業が行われ DesignThemeもDesignFontも バージョン2になりました
しかしメジャーバージョンが アップデートされると ビルドが失敗しました これはパッケージの メジャーバージョンが変わると APIの変更があり得るからです つまりプロジェクト内で 破壊的変更が起こり得ます
ですのでメジャーバージョンを アップデートしたら APIを変更する準備も必要です そのAPIが新たなバージョン内で 動作していてもです
少々手がかかる場合もあるでしょう 今回は時間がないため すでに変更しておきました Lunchアプリケーションの ビルドエラーも解決され DesignThemeバージョン2も 問題なく使えます
ビルドできたので― LunchとDesignFontの間に 直接依存関係を追加します DesignThemeが バージョン2になったので 希望のバージョン要求が追加できます
ではパッケージ追加の ワークフローを進めます “DesignFont”を選び― 2以上で 次のメジャーバージョン未満とします DesignFontライブラリを アプリケーションにリンクできました プロジェクトエディタ内では― 2以上で次のメジャーバージョン未満の DesignFontです
ではDesignFontのコンテンツを インポートしましょう
これでライブラリを使用できます 少しのコード変更で 価格のフォントを変えられます
パッケージ競合が解決できました パッケージバージョンをアップデートし パッケージ解決をデバッグしました
多くの事柄を見てきましたね オープンソースパッケージを プロジェクトで使う方法を確認し そのAPIを使いました
そしてパッケージの詳細を確認し マニフェストの有用性にも触れました Xcodeがパッケージバージョンを 選択する過程も確認しました
そしてパージョンを最新に保つことや アップデートの取得もご説明しました パッケージ競合の解決について ご紹介する中では パッケージのデバッグやバージョンの アップデートにも触れました
GitHubには非常に多くのパッケージが 用意されています あなたのアプリケーションに 取り込めるパッケージがあるかどうか ぜひ確認してみてください
明日のセッションでは 同僚のアンキットとボリスが Swiftパッケージの作成方法を ご説明します パッケージとは何なのかや パッケージの編集などの詳細にも触れ またSwift Package Managerなどに ついてもお話しします Xcodeにおけるパッケージの働きが より詳しく分かるセッションです ぜひご覧ください Swift Package Managerについて ご質問があれば セッション後のラボにお越しください 木曜日と金曜日の12時から開催される Swift Packages Labでも あと2回のセッションがあります ご拝聴いただきありがとうございました (拍手)
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。