
このチュートリアルでは、watchOS 4用のシンプルだが完全に機能するアプリケーションを作成します。具体的には、Apple Watch用のAir Aber航空会社のアプリケーションに取り組みます。
このチュートリアルでは次のことを説明します。
- watchOS 4のターゲットビルドをiOSアプリに追加する方法。
- 2つのターゲットアセンブリ間でデータを交換する方法。
- watchOSインターフェイスコントローラーをStoryboardに追加し、インターフェイスオブジェクトを配置する方法。
-
WKInterfaceController
をサブクラスWKInterfaceController
、すべてをまとめる方法。 - 新しいインターフェイスコントローラーを追加し、テーブルを追加して、行からプロトタイプを作成する方法。
-
WKInterfaceController
クラスをサブクラス化して、テーブルに入力し、行をカスタマイズし、選択を処理する方法。 - インターフェイスコントローラーをモーダルにし、表示用にデータを送信する方法。
- 画像に基づいてアニメーションを作成する方法。
- watchOS 4アニメーションAPIの使用方法。
パート1:はじめに
この部分から次のことを学びます。
- watchOS 4のターゲットビルドをiOSアプリに追加する方法。
- 2つのターゲットアセンブリ間でデータを交換する方法。
- watchOSインターフェイスコントローラーをStoryboardに追加し、インターフェイスオブジェクトを配置する方法。
-
WKInterfaceController
をサブクラスWKInterfaceController
、すべてをまとめる方法。
降りる
このチュートリアルの初期プロジェクトをダウンロードすることから始めましょう。
Xcodeで開き、ビルドして実行します。 空白の白い画面が表示されるはずです。

ご覧のとおり、これまでのところ、このプロジェクトには非常に多くのものがあります。いくつかの必要な補助ファイルがあり、それだけです。 この問題はすぐに解決します!
WatchKitアプリを追加する
ファイル\新規\ターゲット...を選択します。 開いたダイアログで、 watchOS \ Application \ WatchKit Appを選択し、[ 次へ ]をクリックします。

次の画面で、 製品名として「 ウォッチ」という単語を入力し、「 言語」フィールドで「 Swift」が選択されていることを確認し、選択したすべてのチェックボックスをオフにします。 [ 完了 ]をクリックします。

システムは、「ウォッチ」スキームをアクティブにする必要があるかどうかを尋ねます。それが必要になるので、 アクティブ化を選択します。

おめでとうございます、最初のWatchアプリを作成しました! すべてが本当にシンプルです。
このアクションにより、プロジェクトナビゲータで、1つではなく2つのターゲットアセンブリと、2つの対応するグループが実際に作成されたことがわかります。 これは、iOSでToday拡張機能が動作するのと同じように、Watchアプリケーションコードが実際にWatchアプリケーション内に含まれる拡張機能(拡張機能)として実行されるために発生しました。
ProjectナビゲーターでWatchおよびWatch Extensionグループを展開すると、ストーリーボードがWatchグループにあり、ターゲットアセンブリテンプレートによって作成されたクラスがWatch Extensionグループにあることがわかります。

これは、作業で従う順序です。追加されたコードはWatch Extensionグループ内に保存され、ターゲットのWatch Extensionアセンブリに追加され、リソースまたはストーリーボードはWatchグループに追加されます。
少し掃除
続行する前に、置換するターゲットアセンブリテンプレートによって追加されたいくつかの要素を削除する必要があります。
ProjectナビゲータでInterfaceController.swiftを右クリックし、[ 削除]を選択します。 ダイアログボックスで、[ ゴミ箱に移動 ]を選択して、ファイルがプロジェクトから実際に削除されるようにします。

次に、 Interface.storyboardを開き、そこで使用可能な唯一のインターフェイスコントローラーを選択して、 削除ボタンをクリックします。 結果として、空のストーリーボード、または私が好むように空のキャンバスが必要です。
一般的なデータとコード
初期プロジェクトには、Air Aberフライトに関するすべての情報と、このデータを表すモデルクラスを含むJSONファイルがあります。 これは、iOSアプリケーションとWatchアプリケーションが同じクラスのモデルとデータを使用する可能性が高いため、ターゲットアセンブリ間で共通する必要があるものです。DRYの原則を覚えていますか?
プロジェクトナビゲータで共有グループを展開し、 Flights.jsonを選択します。 次に、 ファイルインスペクターで[ ターゲットメンバーシップ]セクションを見つけ、[ ウォッチ拡張機能]チェックボックスをオンにします。

これで、ファイルはAirAberとWatch Extensionの 両方に含まれます。
共有グループ内の別のファイル-Flight.swiftに対してプロセスを繰り返します。
これで、ようやくフライト情報インターフェイスの作成を開始できます!
インターフェイス作成
Watch \ Interface.storyboardを開き、 インターフェイスコントローラーをオブジェクトライブラリからストーリーボードキャンバスにドラッグします 。 インターフェイスコントローラーを選択した状態で、[属性]インスペクターを開き、[ 識別子]を[ フライト]に設定して、[ 初期コントローラー]チェックボックスをオンにします。 ロード時のアクティビティインジケータのチェックを外します。

そのため、コードでインターフェイスコントローラーにアクセスできるように識別子を設定します。 [ イニシャルコントローラー]チェックボックスをオンにすることで、Watchアプリケーションを初めて起動するときにこのインターフェイスコントローラーを表示する必要があることをWatchKitに知らせるだけです。 このインターフェイスはデータをダウンロードしないため、アクティビティインジケータを表示する必要はありません。
このチュートリアルを簡素化するために、42 mm時計のみのインターフェイス図を作成します。 独自のアプリケーションでは、すべての時計サイズで正しく表示されるかどうかを確認する必要があります。 表示方法:ストーリーボードの左下隅でApple Watch 42mmを選択する必要があります。

Watchアプリのレイアウトは、iOSのレイアウトとはまったく異なります。 最初に気付くのは、UIオブジェクトをインターフェイスコントローラーにドラッグして移動または変更できることです。 オブジェクトをコントローラーにドラッグすると、そのオブジェクトは前のオブジェクトの下に配置され、画面がすぐにいっぱいになります。 オブジェクトを一列に並べるには、iOSおよびmacOSのスタックビューに非常に似たグループを使用する必要があります。
そのため、最初に、オブジェクトライブラリからグループ (グループ)をインターフェイスコントローラーにドラッグします。

今のところあまり印象的ではありませんが、このグループには将来的にエアアバーのロゴ、フライト番号、飛行ルートが含まれる予定です。
新しいグループを選択した後、属性インスペクターに移動し、 インセットをカスタムに変更します。 グループのインデントを手動で設定できる4つのテキストフィールドが表示されます。
Topの値を6に変更します。

この方法では、上部にもう少しインデントを追加するだけです。
次に、 画像グループにドラッグアンドドロップします。 グループがインデントに折り畳むことで反応する場合( thanks、Xcode! )、画像をドキュメントアウトラインに直接ドラッグし、次のグループではなくグループの子になることを確認します。

次に、表示された画像が必要です。 このロゴをダウンロードして、 Watch \ Assets.xcassetsにドラッグします。 画像が2倍のスロットを占める新しい画像セットが作成されます。

この画像にコーポレートカラーのAir Aberのタッチを加えたいので、画像を選択し、[ テンプレート画像に レンダリング]の値を変更します。

Watch \ Interface.storyboardを再度開いて、 imageを選択します 。 属性インスペクターを使用して、次の変更を行います。
- Imageの値をLogoに変更します-ドロップダウンメニューに表示されない場合は、キーボードから入力します。
- 色合いの値を#FA114Fに変更します(Color RGB Slidersパネルに入力できます)。
- 40の値で、「 幅」パラメーターを「 固定」に変更します。
- Heightパラメーターを値40で Fixedに変更します。
属性インスペクターは次のようになります。

ロゴが表示されていなくても心配する必要はありません。Xcodeは開発中に画像テンプレートの色相を変更しないようです。 信じてください。アプリケーションをビルドして実行すると、明るいピンク色になります。
次に、作成したグループに別のグループをドラッグし、画像の右側に表示されることを確認してから、属性インスペクターを使用してそのレイアウトをVerticalに変更します。 また、 間隔をカスタム\ 0に変更し、 幅をコンテンツに合わせてサイズに変更します。
次に、2つのラベルを新しいグループにドラッグアンドドロップします。 垂直方向の位置を設定して、ラベルが上下に表示されるようにします。

トップラベルを選択し、属性インスペクターを使用してテキストフィールドにFlight 123を入力し、 テキストカラーを#FA114Fに変更します (RGBパネルを再入力する代わりに、カラーメニューの最近使用したカラーリストからピンクを選択できます)。
次に、下のラベルを選択し、[ テキスト]フィールドにMEL to SFOと入力します。 インターフェイスコントローラーは次のようになります。

このテキストは一時的なものであり、インターフェイスをコントローラークラスに接続すると置き換えられます。
次に、別のグループをインターフェイスコントローラーにドラッグしますが、今回は必ず最初のグループの隣接要素として追加してください。 グループを階層内で正しく配置できない場合は、ドキュメントアウトラインを使用します。

この新しいグループを選択した状態で、 レイアウトを垂直に 、 間隔をカスタム\ 0に設定します。
次に、3つのラベルをこの新しいグループにドラッグアンドドロップします。

ドキュメントのアウトラインで、3つすべてのラベルがグループの横にあるのではなく、グループ内にあることを確認してください
トップラベルを選択し、属性インスペクターをText to AA123 Boardsに変更します。
次に、中央のラベルを選択し、 Textを15:06に置き換えます。 次に、 Text Colorを#FA114Fに、 FontをSystemに変更し、 StyleをRegularに設定して、 Sizeを54に選択します。 最後に、 44の値でHeightをFixedに変更します。
下のラベルを選択し、そのテキストをOn timeに 、 テキストの色を#04DE71に置き換えます。
インターフェイスコントローラーは次のようになります。

次に、別のグループを追加するだけで、このインターフェースが実際のデータを表示できるように、Outletクラスのフィールドの作成に進みます。
新しいグループをオブジェクトライブラリから下のグループにドラッグします。今回は子であり、それを含むグループの一番下にあるはずです。 次に、2つのラベルを追加します 。 これで、インターフェイスオブジェクトの完全な階層は次のようになります。

左ラベルのテキストの属性インスペクターをGate 1Aに設定します。 右ラベルのText値をSeat 64Aに設定し、 Horizontal Alignmentの Rightオプションを選択します。
これで、完成したインターフェースは次のようになります。

おめでとうございます。これで、最初のWatchアプリのインターフェースレイアウトの作成が完了しました。 次に、実際のデータを入力して、シミュレーターでアプリケーションを実行する必要があります。
コントローラーの作成
ProjectナビゲータでWatch Extensionグループを右クリックし、 New File ...を選択します。 開いたダイアログで、 watchOS \ Source \ WatchKit Classを選択し、 Nextをクリックします。 新しいクラスにFlightInterfaceControllerという名前を付け、それが
WKInterfaceController
サブクラスで
WKInterfaceController
、 言語がSwiftに設定されていることを確認します 。

[ 次へ] 、[ 作成]の順にクリックします 。
コードエディターで新しいファイルが開いたら、3つの空のメソッドブランクを削除します。インポートステートメントとクラス定義のみが必要です。
FlightInterfaceController
上に次のアウトレットフィールドを追加します。
@IBOutlet var flightLabel: WKInterfaceLabel! @IBOutlet var routeLabel: WKInterfaceLabel! @IBOutlet var boardingLabel: WKInterfaceLabel! @IBOutlet var boardTimeLabel: WKInterfaceLabel! @IBOutlet var statusLabel: WKInterfaceLabel! @IBOutlet var gateLabel: WKInterfaceLabel! @IBOutlet var seatLabel: WKInterfaceLabel!
ここでは、以前にインターフェイスに配置した各ラベルにアウトレットを追加しました。 間もなく接続します。
次に、アウトレットフィールドの下に次のプロパティとプロパティオブザーバを追加します。
// 1 var flight: Flight? { // 2 didSet { // 3 guard let flight = flight else { return } // 4 flightLabel.setText("Flight \(flight.shortNumber)") routeLabel.setText(flight.route) boardingLabel.setText("\(flight.number) Boards") boardTimeLabel.setText(flight.boardsAt) // 5 if flight.onSchedule { statusLabel.setText("On Time") } else { statusLabel.setText("Delayed") statusLabel.setTextColor(.red) } gateLabel.setText("Gate \(flight.gate)") seatLabel.setText("Seat \(flight.seat)") } }
ここで、各ステップで何が起こるかを示します。
-
Flight
型の補助プロパティを宣言しました。 このクラスはFlight.swiftで宣言されています 。これは、ターゲットのWatch Extension構成に以前に追加された共通コードの一部です。 - プロパティが設定されたときに実行されるプロパティオブザーバを追加しました。
- 補助プロパティに実際にフライトが含まれ、
nil
ではないことを確認します。 正しいFlight
インスタンスがあることがわかっている場合にのみ、タグの構成を続行できます。 - 適切な
flight
プロパティを使用してタグを設定します。 - フライトが遅れる場合、ラベルのテキストの色を赤に変更します。
ここで、コントローラーの最初のディスプレイで
flight
を設定する必要があります。
flight
宣言の下に次の行を追加します。
override func awake(withContext context: Any?) { super.awake(withContext: context) flight = Flight.allFlights().first }
次のパートでは、渡されたコンテキストを使用するようにこの実装を変更しますが、今のところは一般的なJSONファイルからすべてのフライトをロードし、配列から最初のフライトを取得します。
注 :
awake(withContext:)
は、コントローラーがストーリーボードから読み込まれ、そのすべてのアウトレットフィールドが構成された後に呼び出されるため、これは
flight
を設定するのに最適な場所です。
アプリケーションをビルドして実行する前に残っている最後のステップは1つだけです。このステップは、アウトレットフィールドを接続することです。
コンセントフィールドを接続する
Watch \ Interface.storyboardを開き、インターフェイスコントローラーを選択します。 Identityインスペクターを使用して、 Custom Class \ ClassをFlightInterfaceControllerに設定します 。
次に、以下のリストに従ってコンセントフィールドを接続します。
-
flightLabel
:123便 -
routeLabel
:MELからSFO -
boardingLabel
:AA123ボード -
boardTimeLabel
:15:06 -
statusLabel
:時間通り -
gateLabel
:ゲート1A -
seatLabel
:シート64A

アプリケーションを開始する前に、必要なことは1つだけです。 このチュートリアルで開発したアプリケーションの例は42 mmのApple Watch用に作成されたため、正しいシミュレータが設定されていることを確認する必要があります。そうしないと、インターフェイスが少し歪んで見える場合があります。 これらのアプリケーションでは、開発者はすべての時計サイズでインターフェースの動作をテストしますが、これはこのチュートリアルのトピックには適用されません。
[Watch Scheme]メニューを開き、42 mmウォッチシミュレーターのいずれかを選択します。

アプリケーションをビルドして実行します。 シミュレーターのダウンロードが完了すると、正しいインターフェースレイアウトとピンクのAir Aberロゴが表示されます。
Flight
オブジェクトは、着陸時間と座席番号のランダムな値を生成するため、他の値が表示されます。

注 :インストールの失敗に関するメッセージが表示された場合は、Xcodeでプロセスを繰り返すか、クロックシミュレーターでアプリケーションを手動でインストールしてください。 これを行うには、iOSシミュレーターでWatchアプリケーションを開き、 AirAberをタップしてから 、 Apple Watchでアプリを表示するをオンに切り替えます。 その後、クロックシミュレーターに戻り、 Digital Crownをタップしてメイン画面に移動し、AirAberアイコンをタップしてアプリケーションを起動します。
おめでとうございます! 最初のWatchKitインターフェースの実装が完了し、実際のデータを備えたクロックシミュレーターで動作します-すばらしい仕事です!
チュートリアルのこの部分で行ったことの既製の例を次に示します。
パート2:テーブル
チュートリアルの最初の部分では、最初のインターフェイスコントローラーを作成して、watchOS 4の開発の基本について学びました。
シリーズの第2部では、アプリケーションがフライトのリストを表示できるようにテーブルを追加します。
その過程で、次のことを学びます。
- 新しいインターフェイスコントローラーを追加し、テーブルを追加して、行からプロトタイプを作成する方法。
-
WKInterfaceController
クラスをサブクラス化して、テーブルに入力し、行をカスタマイズし、選択を処理する方法。 - インターフェイスコントローラーをモーダルにし、表示用にデータを送信する方法。
仕事を始める
Watch \ Interface.storyboardを開き、別のインターフェイスコントローラーをオブジェクトライブラリからストーリーボードの既存のフライトコントローラーの左側にドラッグします 。
新しいインターフェイスコントローラーを選択した後、属性インスペクターを開き、次の変更を行います。
- IdentifierをScheduleに設定します 。
- [ タイトル]に「 Air Aber」と入力します。
- Is Initial Controllerボックスをチェックします。
- [ 読み込み時のアクティビティインジケータ]チェックボックスがオンになっていることを確認します。
フライトコントローラーと同様に、このインターフェイスコントローラーにコードでアクセスできるように識別子を設定します。 これは、Watchアプリケーションの実際の初期コントローラーであるため、タイトルを設定してチェックボックスをオンにする必要があります。 このコントローラーは、何らかのデータソースからテーブルをロードするため、アクティビティインジケーターを表示します。
それでは、インターフェイスに移りましょう。 テーブルをオブジェクトライブラリから新しいインターフェイスコントローラにドラッグします 。

ドキュメントアウトラインでテーブル行コントローラーを選択します 。

属性インスペクターを使用して、 識別子を FlightRowに設定し ます 。 識別子は、作成する行インスタンスをテーブルに指示するときに行タイプでもあるため、名前を付けることが重要です。
文字列インターフェイスの作成
テーブル行は実際にはグループなので、任意の複雑な構成を指定できます。
最初のタスクは、デフォルトの構成グループに2つの変更を加えることです。 ドキュメントのアウトラインで、テーブルの行内のグループを選択し、属性インスペクターを使用して、 間隔を 6に 、 高さをコンテンツに合わせてサイズに設定します。
デフォルトでは、テーブル行には標準の高さが固定されています。 ただし、ほとんどの場合、追加されたすべてのインターフェイスオブジェクトを表示するためにラインが必要なので、このようにHeight属性を変更する価値が常にあります。
次に、オブジェクトライブラリからテーブル行グループにセパレータをドラッグします。 実際には何も分離しませんが、単にテーブルの行に小さな視覚的なタッチを与えます。 セパレータを選択した後、属性インスペクターを使用して次の変更を行います。
- Colorを#FA114F (以前に使用されたAir Aberのピンク色)に設定します。
- 垂直方向の配置を中央に設定します 。
- コンテナに相対的な 高さに設定します。
- 調整を–4に設定します。
インスペクターは次のようになります。

テーブルの列が突然大きくなり、画面全体に表示されました! しかし、文字列構成を構成するプロセスでこれを修正します。
グループをオブジェクトライブラリから区切り文字の右側のテーブル行にドラッグします。 選択したグループで、属性インスペクターで次の属性を変更します。
- レイアウトを垂直に設定します。
- Spacingを0に設定します 。
- コンテンツに合わせて 幅をサイズに設定します。
おそらく、Spacing属性を頻繁に操作することに気づいたでしょう。 グループのインターフェースのオブジェクト間のスペースを単純に狭め、小さな画面ですべてを少し明確にします。
別のグループを新しく追加したグループにドラッグし、次の変更を加えます。
- 間隔を4に設定します。
- [ 高さ]で、値32の [ 固定]を選択します。
これで、テーブルの行が通常の高さに戻りました!
次に、この新しいグループにラベルと画像を追加します。 ラベルを設定してからコピーして更新し、各フライトの開始点と終了点を表示します。
次に、画像に何かを入れる必要があります。 この画像をダウンロードして、 Watch \ Assets.xcassetsに追加します。 これにより、現在の画像が2xスロットを占める新しい平面画像のセットが作成されます。

この画像にAir Aberのピンク色を与えたいので、画像を選択し、属性インスペクターを使用してRender As値をTemplate Imageに設定します。
Watch \ Interface.storyboardを再度開き、ドキュメントアウトラインで画像を選択します。 属性インスペクターを使用して、次の変更を行います。
- ImageをPlaneに設定します。
- Tintを#FA114Fに設定します。
- 水平および垂直方向の配置をCenterに設定します。
- [ 幅 ]で、値が24の [ 固定 ]オプションを選択します。
- [ 高さ ]で、値20の [ 固定 ]オプションを選択します。
ラベルを選択し、そのテキストフィールドをMELに設定します。 次に、 フォントをシステムに変更し、 セミボールドスタイルとサイズ20にします。 最後に、 垂直方向の配置をCenterに設定します 。
ラベルをコピーして、画像の右側に貼り付けます。 テキストをSFOに変更し、 水平配置を右に変更します。 テーブル行は次のようになります。

注:ラベルのコピーを挿入すると、ドキュメントアウトライン内の位置に関係なく、ラベルが画像の左側に貼り付けられることがあります。ただし、水平方向の配置を右に設定すると、所定の位置に移動します。
インターフェイスオブジェクトの階層は次のようになります。

テーブル行インターフェイスはほぼ完成しました。フライト番号とステータスのみを追加します。
別のグループをオブジェクトライブラリからテーブルの行にドラッグして、出発ラベルと到着ラベルを含むグループの隣に配置します。

このインターフェイスの作成を続けると、複雑な構成を作成するために、構成が混在する組み込みグループを使用する方法の他の例が表示されます。この自動レイアウトが必要なのは誰ですか?!
この新しい水平グループに2つのラベルをドラッグします。属性インスペクターを使用して、左側のラベルを変更します。
- TextをAA123に設定します。
- テキストの色を明るい灰色に設定します。
- フォントをキャプション2に設定します。
- Vertical AlignmentをBottomに設定します。
次に、適切なラベルを変更します。
- TextをOn timeに設定します。
- テキストの色を#04DE71に設定します。
- フォントをキャプション2に設定します。
- Horizontal AlignmentをRightに設定します。
- Vertical AlignmentをBottomに設定します。
これらの最後の変更を行った後、テーブルの完成した行は次のようになります。

Interface Builderでテーブルを設定したら、いくつかのデータを入力することができます。
テーブル充填
最初に行うことは
WKInterfaceController
、テーブルを管理するクラスのサブクラスを作成することです。
グループを右クリックしウォッチ拡張プロジェクトナビゲータでを選択し新規...ファイルを。表示されるダイアログで、watchOS \ Source \ WatchKit Classを選択し、Nextをクリックします。新しいクラスにScheduleInterfaceControllerという名前を付けます。WKInterfaceControllerのサブクラスであり、言語がSwiftに設定されていることを確認します。

[ 次へ]、[ 作成]の順にクリックします。
コードエディターで新しいファイルが開いたら、インポートステートメントとクラス定義のみが残るように、3つの空のメソッドブランクを削除します。Watch \ Interface.storyboardを
再度開き、新しいインターフェイスコントローラーを選択します。Identityインスペクターで、Custom Class \ ClassをScheduleInterfaceControllerに置き換えます。

インターフェイスコントローラーを選択したまま、アシスタントエディターを開き、そこに表示されていることを確認します
ScheduleInterfaceController
。次に、Controlキーを押しながら、テーブルからドキュメントのアウトラインにクラス定義
ScheduleInterfaceController
にドラッグして、Outletフィールドを作成します。

コールアウトレットショッピングflightsTableは、それがタイプに設定されていることを確認しWKInterfaceTableをクリックし、接続を。
独自のクラスを設定し、テーブルにOutletを作成したので、それを設定します。
アシスタントエディターを閉じ、ScheduleInterfaceController.swiftを開き、アウトレットの直後に次の行を追加します。
var flights = Flight.allFlights()
ここでは、すべてのフライト情報を含むプロパティをインスタンスの配列として追加するだけ
Flight
です。
次に、次の実装を追加します
awake(withContext:)
。
override func awake(withContext context: Any?) { super.awake(withContext: context) flightsTable.setNumberOfRows(flights.count, withRowType: "FlightRow") }
ここで、の各フライトに対してInterface Builderで作成した行をインスタンス化する必要があることをテーブルに通知します
flights
。行数は配列のサイズに等しく、行タイプはストーリーボードで設定した識別子です。
アプリケーションをビルドして実行します。いくつかの行で満たされたテーブルが表示されます。各行の隣には、エアアバーの飛行機のピンクの画像があります。

しかし、ちょっと待ってください!タイトルは、ホットピンクのコーポレートカラーであるAir Aberではなく、ダークグレーです。今それを修正します。Watch \ Interface.storyboardを
開き、Air Aberインターフェイスコントローラーを選択します。ファイルインスペクタで、グローバルティントを#FA114Fに変更します。

アプリケーションをビルドして実行します。それは良いです!

しかし、今ではすべての行に、Interface Builderで設定したプレースホルダーテキストが表示されていることがわかります。次に、行ごとにラベルを設定する行コントローラーを追加して、これを修正します。
行コントローラーの追加
WatchKitテーブルはiOSテーブルよりもはるかに単純です。ここにはデータソースやデリゲートはありません。行コントローラークラスを作成するだけです。これは、名前にもかかわらず、クラスのサブクラスです
NSObject
。
グループを右クリックしウォッチ拡張プロジェクトナビゲータでを選択し新規...ファイルを。開いたダイアログボックスで、watchOS \ Source \ WatchKit Classを選択し、Nextをクリックします。新しいクラスにFlightRowControllerという名前を付けます。それはのサブクラスであることを確認しNSObjectの、 -およびない WKInterfaceController! -そして、その言語はSwiftが重要です:

[ 次へ]、[ 作成]の順にクリックします。
コードエディタで新しいファイルが開いたら、クラスの先頭に次の行を追加します。
@IBOutlet var separator: WKInterfaceSeparator! @IBOutlet var originLabel: WKInterfaceLabel! @IBOutlet var destinationLabel: WKInterfaceLabel! @IBOutlet var flightNumberLabel: WKInterfaceLabel! @IBOutlet var statusLabel: WKInterfaceLabel! @IBOutlet var planeImage: WKInterfaceImage!
ここでは、テーブル行に追加された各ラベルにアウトレットを追加するだけです。間もなく接続します。
次に、アウトレットフィールドのすぐ下に、次のプロパティとプロパティオブザーバーを追加します。
// 1 var flight: Flight? { // 2 didSet { // 3 guard let flight = flight else { return } // 4 originLabel.setText(flight.origin) destinationLabel.setText(flight.destination) flightNumberLabel.setText(flight.number) // 5 if flight.onSchedule { statusLabel.setText("On Time") } else { statusLabel.setText("Delayed") statusLabel.setTextColor(.red) } } }
各段階で何が起こるかを次に示します。
- 型の補助プロパティを宣言します
Flight
。このクラスはFlight.swiftで宣言されています。これは、チュートリアルの前の部分でWatch Extensionに追加された一般的なコードの一部です。 - プロパティが設定されたときに実行されるプロパティオブザーバを追加します。
- ,
flight
nil
: ,Flight
. -
flight
. - , .
行コントローラーの構成が完了したら、それを使用するためにテーブルの行を更新する必要があります。Watch \ Interface.storyboardを
開き、ドキュメントアウトラインでFlightRowを選択します。 Identityインスペクターを使用して、Custom Class \ ClassをFlightRowControllerに設定します。ドキュメントアウトライン、すべてのグループを開くFlightRow、その後を右クリックFlightRowアクションのポップアップウィンドウやアウトレットのフィールドを引き起こすために、:

このポップアップを右にドラッグして、FlightRowのすべてのオブジェクトを表示できます。
まず、
planeImage
テーブルの行の画像と
separator
セパレーターに接続します。次に、以下のリストに従って、残りのアウトレットフィールドを接続します。
-
destinationLabel
:SFO -
flightNumberLabel
:AA123 -
originLabel
:MEL -
statusLabel
:時間通り
最後の手順は、テーブル内の各行コントローラーに
ScheduleInterfaceController
インスタンスを渡すように更新すること
Flight
です。ScheduleInterfaceController.swiftを
開き、次の行を追加します。
awakeWithContext(_:)
for index in 0..<flightsTable.numberOfRows { guard let controller = flightsTable.rowController(at: index) as? FlightRowController else { continue } controller.flight = flights[index] }
ここ
for
で、テーブル内の各行をループし、対応するインデックスを使用して行コントローラーのテーブルを照会します。コントローラーを正しくリクエストすると、インスタンスが取得されます
FlightRowController
。次に、
controller.flight
対応する要素
flight
を配列に設定し
flights
ます。これにより、オブザーバーが実行
didSet
さ
FlightRowController
れ、テーブル行のすべてのラベルが設定されます。
作業の結果を確認するときです。アプリケーションをビルドして実行します。テーブル行に正しいフライト情報が入力されていることがわかります。

そして今、チュートリアルのこの部分の最後のタスク:ユーザーがテーブルの行をタッチすると
ScheduleInterfaceController
、対応するフライトをコンテキストとして、チュートリアルの前の部分で作成したフライト情報インターフェイスに転送し、表示する必要があります。
選択した文字列に一致
最初に行うことは
WKInterfaceTable
、テーブル行を選択する処理を実行するメソッドをオーバーライドすることです。次の行に
追加し
ScheduleInterfaceController
ます。
override func table(_ table: WKInterfaceTable, didSelectRowAt rowIndex: Int) { let flight = flights[rowIndex] presentController(withName: "Flight", context: flight) }
ここでは
flights
、このメソッドに渡された行インデックスを使用して、対応するフライトから取得します。次に、
context
送信の品質で、フライトの詳細インターフェイスを表示します
flight
。渡される名前
presentController(withName:context:)
は、チュートリアルの前の部分でストーリーボードに設定した識別子です。
さて、最初の部分で約束したように、
FlightInterfaceController
それ
context
を使用してインターフェースを構成するように変更します。FlightInterfaceController.swiftを
開き、を見つけます。この行を見つけます:
awake(withContext:)
flight = Flight.allFlights().first
次の行に置き換えます。
if let flight = context as? Flight { self.flight = flight }
ここでは
context
、インスタンスとして変換しようとしています
Flight
。これが成功した場合、それをjob
self.flight
に使用します。これにより、プロパティオブザーバーが実行され、インターフェイスが構成されます。
このパートでは、最後にアプリケーションをビルドして実行します。表の行をタッチすると、選択されたフライトに関する情報とともに、フライト情報インターフェースがモーダルでどのように表示されるかがわかります。

おめでとうございます! 最初のテーブルの実装が完了し、実際のデータが入力されました。 素晴らしい仕事です!
ここでプロジェクトの準備ができて例我々は、このチュートリアルでは、これまで行われていること。
パート3:アニメーション
チュートリアルの第3部では、アプリケーションの例として、新しいフライト登録インターフェイスを使用してwatchOS 4アニメーションを使用する方法を学習します。
その過程で、次のことを学びます。
- 画像に基づいてアニメーションを作成する方法。
- watchOS 4アニメーションAPIの使用方法。
仕事を始める
Watch \ Interface.storyboardを開き、インターフェイスコントローラーをオブジェクトライブラリからストーリーボードキャンバスにドラッグします。コントローラインターフェイスを選択した後、属性インスペクタを開き、に入力する識別子値チェックイン。これを実行して、からインターフェイスコントローラーを定義できるようにしました
ScheduleInterfaceController
。
次に、オブジェクトライブラリグループから新しいインターフェイスコントローラーにドラッグします。属性インスペクターで、次の変更を行います。
- [ レイアウト]を[ 垂直]に設定します。
- ModeをCenterに設定します。
- Horizontal AlignmentをCenterに設定します。
- コンテナに相対的な高さに設定します。
インターフェイスコントローラーは次のようになります。

次に、テーブル行用に作成したlabel-image-labelから同じグループを作成します。
別のグループを作成したグループにドラッグし、属性インスペクターに次の変更を加えます。
- Spacingを4に設定します。
- Horizontal AlignmentをCenterに設定します。
- コンテンツに合わせて幅をサイズに設定します。
- 30の値(テーブル行より少し短い)で[ 高さ ]オプション[ 固定 ]を選択します。
この新しいグループにラベルと画像を追加します。ラベルを設定してからコピーして更新し、各フライトの開始点と終了点を表示します。
ストーリーボードまたはドキュメントのアウトラインで画像を選択します。属性インスペクターで、次の変更を行います。
- ImageをPlaneに設定します。
- Tintを#FA114Fに設定します(これもピンク色です!)。
- 垂直方向の配置を中央に設定します。
- 24の値で[ 幅 ]オプション[ 固定 ]を選択します。
- Height Fixed 20 .
前と同様に、画像は色相を変更しないため、インターフェイスコントローラーの黒い背景には表示されません。しかし、私たちはそれがそこにあることを知っています。
ラベルを選択し、テキスト値をMELに設定します。次に、フォントをシステムに変更し、セミボールドスタイルとサイズ20にします。最後に、垂直方向の配置をCenterに設定し、幅と高さがコンテンツに合わせてサイズに設定されていることを確認します。
ラベルをコピーして、画像の横に貼り付けます。テキストをSFOに、水平方向の配置を右。インターフェイスコントローラーは次のようになります。

さあ、巨大な登録ボタンを追加しましょう!
登録ボタンを追加
ボタンをオブジェクトライブラリからインターフェイスコントローラーにドラッグし、フライトの開始点と終了点のラベルを含むグループに隣接する要素であることを確認します。

WatchKitのボタンは非常に柔軟です。デフォルトの外観(今追加したような外観)で使用したり、レイアウトグループに変えて他のインターフェイスオブジェクトを追加して外観をカスタマイズしたりできます。それが私たちのすることです。
ボタンを選択し、属性インスペクターに次の変更を加えます。
- コンテンツをグループに設定します。
- Horizontal AlignmentをCenterに設定します。
- 垂直方向の配置を中央に設定します。
インターフェイスコントローラーは次のようになります。

ボタンのコンテンツ属性を変更すると、ドキュメントアウトラインに新しいグループが表示されることに気づいたでしょう。

独自の登録ボタンの背景として使用します。このグループを選択し、属性インスペクターに次の変更を加えます。
- [ 色]を#FA114Fに設定します。
- 半径を39に設定します。
- 78の値で[ 幅 ]オプション[ 固定 ]を選択します。
- 78の値で[ 高さを固定]を選択します。
インターフェイスコントローラーは次のようになります。

登録ボタンはすでにその形を取り始めています。不足しているのはラベルだけなので、ここで追加します。オブジェクトライブラリからボタンに属するグループにラベルを
ドラッグし、選択します。次の変更を再度属性インスペクターにします。
- TextをCheck Inに設定します。
- フォントをシステムに設定し、セミボールドスタイルとサイズ16にします。
- Horizontal AlignmentをCenterに設定します。
- 垂直方向の配置を中央に設定します。
登録インターフェースの完成したコントローラーは次のようになります。

インターフェースが完成したら、
WKInterfaceController
このコントローラーを制御するサブクラスの作成に進み
ScheduleInterfaceController
、表示するように変更します。
コントローラーの作成
グループを右クリックしウォッチ拡張プロジェクトナビゲータでを選択し新規...ファイルを。表示されるダイアログで、watchOS \ Source \ WatchKit Classを選択し、Nextをクリックします。新しいクラスにCheckInInterfaceControllerという名前を付け、それがWKInterfaceControllerのサブクラスであり、SwiftがLanguageに選択されていることを確認します。

[ 次へ]、[ 作成]の順にクリックします。
コードエディターで新しいファイルが開いたら、インポートステートメントとクラス定義のみが含まれるように、3つの空のメソッドブランクを削除します。
次に、クラスの上部に次の行を追加します。
@IBOutlet var backgroundGroup: WKInterfaceGroup! @IBOutlet var originLabel: WKInterfaceLabel! @IBOutlet var destinationLabel: WKInterfaceLabel!
ここでは、最も外側のグループのアウトレットフィールドと、作成した2つのインターフェイスラベルを追加します。すぐにそれらすべてを接続します。
次に、[アウトレット]フィールドの下に次を追加します。
var flight: Flight? { didSet { guard let flight = flight else { return } originLabel.setText(flight.origin) destinationLabel.setText(flight.destination) } }
ここ
Flight
では、プロパティオブザーバーを含む補助型プロパティを追加しました。オブザーバーは、実行時にからラッパーを削除しようとし
flight
、成功した場合は、
flight
2つのラベルを使用して構成します。これはすべて私たちにすでによく知られています。
ここ
flight
で、コントローラーがあるかどうかを設定するだけです。
CheckInInterfaceController
次の行に追加します。
override func awake(withContext context: Any?) { super.awake(withContext: context) if let flight = context as? Flight { self.flight = flight } }
あなたはすでにこれに精通しています。ラッパーを削除し
context
て、インスタンスに変換しようとしています
Flight
。これが成功した場合、タスクに使用し
self.flight
、プロパティオブザーバを実行して、インターフェイスを設定します。
最後に、
awake(withContext:)
次のアクションのすぐ下に追加します。
@IBAction func checkInButtonTapped() { // 1 let duration = 0.35 let delay = DispatchTime.now() + (duration + 0.15) // 2 backgroundGroup.setBackgroundImageNamed("Progress") // 3 backgroundGroup.startAnimatingWithImages(in: NSRange(location: 0, length: 10), duration: duration, repeatCount: 1) // 4 DispatchQueue.main.asyncAfter(deadline: delay) { [weak self] in // 5 self?.flight?.checkedIn = true self?.dismiss() } }
ここで、各ステップで何が起こるかを示します。
- 2つの定数を作成します。1つはアニメーションの継続時間用、もう1つは遅延用で、その後コントローラーがオフになります。
delay
-これはDouble
インスタンスDispatchTime
ではなく、Grand Central Dispatchで使用するためです。 - Progress
backgroundGroup
.WKImageAnimatable
, . - . ,
repeatCount
, 1, , . - WatchKit , Grand Central Dispatch .
- ,
flight
, .
ここで、プロジェクトに画像を追加し、アウトレットと1つのアクションを接続するだけです。このzipファイルを
ダウンロードして解凍し、フォルダーをWatch \ Assets.xcassetsにドラッグします。
内容ではなくフォルダをドラッグアンドドロップします。これにより、Progressという名前のリソースディレクトリにグループが作成され、いくつかの画像セットが含まれます。

画像を追加することで、アウトレットフィールドとボタンアクションを割り当てることができます。Watch \ Interface.storyboardを
開き、新しいインターフェイスコントローラーを選択します。Identityインスペクターで、Custom Class \ ClassをCheckInInterfaceControllerに置き換えます。

次に、ドキュメントアウトラインでCheckInを右クリックして、アウトレットフィールドとアクションを表示します。
backgroundGroup
インターフェイスコントローラーの最も外側のグループに接続します。

ストーリーボードキャンバスで
destinationLabel
、SFOを
originLabel
含むラベルに接続し、MELを含むラベルに接続します。
次に
checkInButtonTapped
、大きな丸いピンクのボタンに接続します。

アプリケーションをビルドして実行する前に、最後の変更、つまりインターフェイスコントローラーの表示を行う必要があります。
コントローラーのマッピング
ScheduleInterfaceController.swiftを開き、
table(_:didSelectRowAt:)
その内容を見つけて次の行に置き換えます。
let flight = flights[rowIndex] let controllers = ["Flight", "CheckIn"] presentController(withNames: controllers, contexts: [flight, flight])
ここ
flights
で、インデックス
rowIndex
を使用して対応するフライトを取得し、表示する2つのインターフェイスコントローラーの識別子を含む配列を作成し、それらを表示して、両方を
flight
quality で渡します
context
。
アプリケーションをビルドして実行します。フライトをタッチすると、表示されているインターフェイスコントローラーがいくつか表示されます。左にスワイプして登録コントローラーを開き、ボタンをタップしてアニメーションを開始して登録します。

これはそれ自体で素晴らしいように見えますが、チェックインされているフライトがスケジュールインターフェイスコントローラーで強調表示されている方が良いです。これは、次の最後のセクションで行います。
フライトハイライト
FlightRowController.swiftを開き、次のメソッドを追加します。
func updateForCheckIn() { let color = UIColor(red: 90/255, green: 200/255, blue: 250/255, alpha: 1) planeImage.setTintColor(color) separator.setColor(color) }
ここでは、インスタンスを作成し
UIColor
、それぞれ、色調や色を設定するためにそれを使用し、その後、
planeImage
と
separator
。このメソッドは、アニメーションが閉じるときに呼び出されるため、色の変化が美しくアニメーション化されます。
次に、ScheduleInterfaceController.swiftを開き、
flights
次のプロパティを追加します。
var selectedIndex = 0
2つのインターフェイスコントローラーを表示するときに、テーブルのどの行が選択されているかを記憶するために使用します。これで、表の行を選択するときに設定するだけで十分です。直接呼び出しの上に次の行を追加
presentController(withNames:contexts:)
します
table(_:didSelectRowAt:)
:
selectedIndex = rowIndex
この行は
selectedIndex
、テーブル内の選択された行のインデックス値を設定します。
最後に、次の行をの
ScheduleInterfaceController
すぐ下に追加します
awake(withContext:)
。
override func didAppear() { super.didAppear() // 1 guard flights[selectedIndex].checkedIn, let controller = flightsTable.rowController(at: selectedIndex) as? FlightRowController else { return } // 2 animate(withDuration: 0.35) { // 3 controller.updateForCheckIn() } }
各段階で何が起こるかを次に示します。
- 選択したフライトのチェックインが完了しているかどうかを確認してください。もしそうなら、テーブル内の対応するインデックスを持つ行コントローラをインスタンスに変換しようとしています
FlightRowController
。 - これが成功した場合、アニメーションAPIを使用し
WKInterfaceController
て、0.35秒でクロージャを実行します。 - 閉じるときに、に追加したメソッドを呼び出します
FlightRowController
。これにより、画像の色とテーブルのこの行のセパレータが変更され、登録が完了したことを知らせる視覚的なフィードバックがユーザーに提供されます。
アプリケーションをビルドして実行します。前と同じ手順に従ってフライトに登録すると、スケジュールインターフェイスのコントローラーに戻り、テーブルの対応する行の画像とセパレーターの色が次第に新しい色に変わります。

おめでとうございます!WatchKitアニメーションの最初のセットの実装が完了しました。
ここでプロジェクトの準備例このチュートリアルで行っています。
このパートでは、2種類のWatchKitアニメーションを作成する方法を学びました。最初はアニメーション化された一連の画像を
WKInterfaceController
使用し、2番目はアニメーションAPIを使用しました。