チュートリアル:watchOS 4用のシンプルなアプリケーションの作成

画像






このチュートリアルでは、watchOS 4用のシンプルだが完全に機能するアプリケーションを作成します。具体的には、Apple Watch用のAir Aber航空会社のアプリケーションに取り組みます。



このチュートリアルでは次のことを説明します。





パート1:はじめに



この部分から次のことを学びます。





降りる



このチュートリアルの初期プロジェクトをダウンロードすることから始めましょう。



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を選択します。 次に、 ファイルインスペクターで[ ターゲットメンバーシップ]セクションを見つけ、[ ウォッチ拡張機能]チェックボックスをオンにします。









これで、ファイルはAirAberWatch 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を選択します 。 属性インスペクターを使用して、次の変更を行います。





属性インスペクターは次のようになります。











ロゴが表示されていなくても心配する必要はありません。Xcodeは開発中に画像テンプレートの色相を変更しないようです。 信じてください。アプリケーションをビルドして実行すると、明るいピンク色になります。



次に、作成したグループに別のグループをドラッグし、画像の右側に表示されることを確認してから、属性インスペクターを使用してそのレイアウトVerticalに変更します。 また、 間隔カスタム\ 0に変更し、 コンテンツに合わせサイズに変更します。



次に、2つのラベルを新しいグループにドラッグアンドドロップします。 垂直方向の位置を設定して、ラベルが上下に表示されるようにします。









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



次に、下のラベルを選択し、[ テキスト]フィールドにMEL to SFOと入力します。 インターフェイスコントローラーは次のようになります。











このテキストは一時的なものであり、インターフェイスをコントローラークラスに接続すると置き換えられます。



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









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



次に、3つのラベルをこの新しいグループにドラッグアンドドロップします。









ドキュメントのアウトラインで、3つすべてのラベルがグループの横にあるのではなくグループ内にあることを確認してください



トップラベルを選択し、属性インスペクターをText to AA123 Boardsに変更します。



次に、中央のラベルを選択し、 Text15:06に置き換えます。 次に、 Text Color#FA114Fに、 FontSystemに変更し、 StyleRegularに設定して、 Size54に選択します。 最後に、 44の値でHeightFixedに変更します。



下のラベルを選択し、そのテキストOn timeにテキストの色#04DE71に置き換えます。



インターフェイスコントローラーは次のようになります。









次に、別のグループを追加するだけで、このインターフェースが実際のデータを表示できるように、Outletクラスのフィールドの作成に進みます。



新しいグループをオブジェクトライブラリから下のグループにドラッグします。今回は子であり、それを含むグループの一番下にあるはずです。 次に、2つのラベルを追加します 。 これで、インターフェイスオブジェクトの完全な階層は次のようになります。









左ラベルのテキストの属性インスペクターをGate 1Aに設定します。 右ラベルのText値をSeat 64Aに設定し、 Horizo​​ntal 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)") } }
      
      





ここで、各ステップで何が起こるかを示します。



  1. Flight



    型の補助プロパティを宣言しました。 このクラスはFlight.swiftで宣言されています 。これは、ターゲットのWatch Extension構成に以前に追加された共通コードの一部です。
  2. プロパティが設定されたときに実行されるプロパティオブザーバを追加しました。
  3. 補助プロパティに実際にフライトが含まれ、 nil



    ではないことを確認します。 正しいFlight



    インスタンスがあることがわかっている場合にのみ、タグの構成を続行できます。
  4. 適切なflight



    プロパティを使用してタグを設定します。
  5. フライトが遅れる場合、ラベルのテキストの色を赤に変更します。


ここで、コントローラーの最初のディスプレイで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 \ ClassFlightInterfaceControllerに設定します



次に、以下のリストに従ってコンセントフィールドを接続します。













アプリケーションを開始する前に、必要なことは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部では、アプリケーションがフライトのリストを表示できるようにテーブルを追加します。



その過程で、次のことを学びます。





仕事を始める



Watch \ Interface.storyboardを開き、別のインターフェイスコントローラーをオブジェクトライブラリからストーリーボードの既存のフライトコントローラーの左側にドラッグします



新しいインターフェイスコントローラーを選択した後、属性インスペクターを開き、次の変更を行います。





フライトコントローラーと同様に、このインターフェイスコントローラーにコードでアクセスできるように識別子を設定します。 これは、Watchアプリケーションの実際の初期コントローラーであるため、タイトルを設定してチェックボックスをオンにする必要があります。 このコントローラーは、何らかのデータソースからテーブルをロードするため、アクティビティインジケーターを表示します。



それでは、インターフェイスに移りましょう。 テーブルをオブジェクトライブラリから新しいインターフェイスコントローラにドラッグします









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









属性インスペクターを使用して、 識別子を FlightRowに設定 ます 。 識別子は、作成する行インスタンスをテーブルに指示するときに行タイプでもあるため、名前を付けることが重要です。



文字列インターフェイスの作成



テーブル行は実際にはグループなので、任意の複雑な構成を指定できます。



最初のタスクは、デフォルトの構成グループに2つの変更を加えることです。 ドキュメントのアウトラインで、テーブルの行内のグループを選択し、属性インスペクターを使用して、 間隔を 6にをコンテンツに合わせサイズに設定します。



デフォルトでは、テーブル行には標準の高さが固定されています。 ただし、ほとんどの場合、追加されたすべてのインターフェイスオブジェクトを表示するためにラインが必要なので、このようにHeight属性を変更する価値が常にあります。



次に、オブジェクトライブラリからテーブル行グループにセパレータをドラッグします。 実際に何も分離しませんが、単にテーブルの行に小さな視覚的なタッチを与えます。 セパレータを選択した後、属性インスペクターを使用して次の変更を行います。





インスペクターは次のようになります。











テーブルの列が突然大きくなり、画面全体に表示されました! しかし、文字列構成を構成するプロセスでこれを修正します。



グループをオブジェクトライブラリから区切り文字の右側のテーブル行にドラッグします。 選択したグループで、属性インスペクターで次の属性を変更します。





おそらく、Spacing属性を頻繁に操作することに気づいたでしょう。 グループのインターフェースのオブジェクト間のスペースを単純に狭め、小さな画面ですべてを少し明確にします。



別のグループを新しく追加したグループにドラッグし、次の変更を加えます。





これで、テーブルの行が通常の高さに戻りました!



次に、この新しいグループにラベル画像を追加します。 ラベルを設定してからコピーして更新し、各フライトの開始点と終了点を表示します。



次に、画像に何かを入れる必要があります。 この画像をダウンロードして、 Watch \ Assets.xcassetsに追加します。 これにより、現在の画像が2xスロットを占める新しい平面画像のセットが作成されます。









この画像にAir Aberのピンク色を与えたいので、画像を選択し、属性インスペクターを使用してRender As値をTemplate Imageに設定します。



Watch \ Interface.storyboardを再度開き、ドキュメントアウトラインで画像を選択します。 属性インスペクターを使用して、次の変更を行います。





ラベルを選択し、そのテキストフィールドをMELに設定します。 次に、 フォントシステムに変更し、 セミボールドスタイルとサイズ20にします。 最後に、 垂直方向の配置Centerに設定します



ラベルをコピーして、画像の右側に貼り付けます。 テキストをSFOに変更し、 水平配置右に変更します。 テーブル行は次のようになります。









:ラベルのコピーを挿入すると、ドキュメントアウトライン内の位置に関係なく、ラベルが画像の左側に貼り付けられることがあります。ただし、水平方向の配置を設定すると、所定の位置に移動します。



インターフェイスオブジェクトの階層は次のようになります。









テーブル行インターフェイスはほぼ完成しました。フライト番号とステータスのみを追加します。



別のグループをオブジェクトライブラリからテーブルの行にドラッグして、出発ラベルと到着ラベルを含むグループの隣に配置します。









このインターフェイスの作成を続けると、複雑な構成を作成するために、構成が混在する組み込みグループを使用する方法の他の例が表示されます。この自動レイアウトが必要なのは誰ですか?!



この新しい水平グループに2つのラベルをドラッグします。属性インスペクターを使用して、左側のラベルを変更します。





次に、適切なラベルを変更します。





これらの最後の変更を行った後、テーブルの完成した行は次のようになります。









Interface Builderでテーブルを設定したら、いくつかのデータを入力することができます。



テーブル充填



最初に行うことはWKInterfaceController



、テーブルを管理するクラスのサブクラスを作成することです



グループを右クリックしウォッチ拡張プロジェクトナビゲータでを選択し新規...ファイルを。表示されるダイアログで、watchOS \ Source \ WatchKit Class選択し、Nextをクリックします。新しいクラスにScheduleInterfaceControllerという名前を付けますWKInterfaceControllerのサブクラスであり、言語Swiftに設定されていることを確認します









[ 次へ][ 作成]の順にクリックします



コードエディターで新しいファイルが開いたら、インポートステートメントとクラス定義のみが残るように、3つの空のメソッドブランクを削除します。Watch \ Interface.storyboard



再度開き、新しいインターフェイスコントローラーを選択します。Identityインスペクターで、Custom Class \ ClassScheduleInterfaceControllerに置き換えます









インターフェイスコントローラーを選択したまま、アシスタントエディターを開き、そこに表示されていることを確認します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) } } }
      
      





各段階で何が起こるかを次に示します。



  1. 型の補助プロパティを宣言しますFlight



    このクラスはFlight.swift宣言されています。これは、チュートリアルの前の部分でWatch Extensionに追加された一般的なコードの一部です。
  2. プロパティが設定されたときに実行されるプロパティオブザーバを追加します。
  3. , flight



    nil



    : , Flight



    .
  4. flight



    .
  5. , .


行コントローラーの構成が完了したら、それを使用するためにテーブルの行を更新する必要があります。Watch \ Interface.storyboard



開き、ドキュメントアウトラインでFlightRowを選択します。 Identityインスペクターを使用して、Custom Class \ ClassFlightRowControllerに設定します。ドキュメントアウトライン、すべてのグループを開くFlightRow、その後を右クリックFlightRowアクションのポップアップウィンドウやアウトレットのフィールドを引き起こすために、:













このポップアップを右にドラッグして、FlightRowのすべてのオブジェクトを表示できます



まず、planeImage



テーブルの行の画像とseparator



セパレーターに接続します。次に、以下のリストに従って、残りのアウトレットフィールドを接続します。





最後の手順は、テーブル内の各行コントローラーに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アニメーションを使用する方法を学習します。



その過程で、次のことを学びます。





仕事を始める



Watch \ Interface.storyboard開きインターフェイスコントローラーをオブジェクトライブラリからストーリーボードキャンバスにドラッグしますコントローラインターフェイスを選択した後、属性インスペクタを開き、に入力する識別子チェックインこれを実行して、からインターフェイスコントローラーを定義できるようにしましたScheduleInterfaceController







次に、オブジェクトライブラリグループから新しいインターフェイスコントローラーにドラッグします。属性インスペクターで、次の変更を行います。





インターフェイスコントローラーは次のようになります。









次に、テーブル行用に作成したlabel-image-labelから同じグループを作成します。



別のグループを作成したグループドラッグし、属性インスペクターに次の変更を加えます。





この新しいグループにラベル画像を追加します。ラベルを設定してからコピーして更新し、各フライトの開始点と終了点を表示します。



ストーリーボードまたはドキュメントのアウトラインで画像を選択します。属性インスペクターで、次の変更を行います。





前と同様に、画像は色相を変更しないため、インターフェイスコントローラーの黒い背景には表示されません。しかし、私たちはそれがそこにあることを知っています。



ラベルを選択し、テキスト値をMELに設定します。次に、フォントシステムに変更し、セミボールドスタイルとサイズ20にします。最後に、垂直方向の配置Center設定し高さコンテンツに合わせてサイズに設定されていることを確認します。



ラベルをコピーして、画像の横に貼り付けます。テキストをSFOに、水平方向の配置インターフェイスコントローラーは次のようになります。









さあ、巨大な登録ボタンを追加しましょう!



登録ボタンを追加



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









WatchKitのボタンは非常に柔軟です。デフォルトの外観(今追加したような外観)で使用したり、レイアウトグループに変えて他のインターフェイスオブジェクトを追加して外観をカスタマイズしたりできます。それが私たちのすることです。



ボタンを選択し、属性インスペクターに次の変更を加えます。





インターフェイスコントローラーは次のようになります。









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









独自の登録ボタンの背景として使用します。このグループを選択し、属性インスペクターに次の変更を加えます。





インターフェイスコントローラーは次のようになります。









登録ボタンはすでにその形を取り始めています。不足しているのはラベルだけなので、ここで追加します。オブジェクトライブラリからボタンに属するグループにラベル



ドラッグし、選択します。次の変更を再度属性インスペクターにします。





登録インターフェースの完成したコントローラーは次のようになります。









インターフェースが完成したら、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() } }
      
      





ここで、各ステップで何が起こるかを示します。



  1. 2つの定数を作成します。1つはアニメーションの継続時間用、もう1つは遅延用で、その後コントローラーがオフになります。delay



    -これはDouble



    インスタンスDispatchTime



    はなくGrand Central Dispatchで使用するためです。
  2. Progress backgroundGroup



    . WKImageAnimatable



    , .
  3. . , repeatCount



    , 1, , .
  4. WatchKit , Grand Central Dispatch .
  5. , flight



    , .


ここで、プロジェクトに画像を追加し、アウトレットと1つのアクションを接続するだけです。このzipファイルを



ダウンロードし解凍し、フォルダーをWatch \ Assets.xcassetsにドラッグします



内容ではなくフォルダをドラッグアンドドロップします。これにより、Progressという名前のリソースディレクトリにグループが作成され、いくつかの画像セットが含まれます。









画像を追加することで、アウトレットフィールドとボタンアクションを割り当てることができます。Watch \ Interface.storyboard



開き、新しいインターフェイスコントローラーを選択します。Identityインスペクターで、Custom Class \ ClassCheckInInterfaceControllerに置き換えます。









次に、ドキュメントアウトラインでCheckIn右クリックして、アウトレットフィールドとアクションを表示します。backgroundGroup



インターフェイスコントローラーの最も外側のグループに接続します。









ストーリーボードキャンバスでdestinationLabel



SFOoriginLabel



含むラベルに接続し、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() } }
      
      





各段階で何が起こるかを次に示します。



  1. 選択したフライトのチェックインが完了しているかどうかを確認してください。もしそうなら、テーブル内の対応するインデックスを持つ行コントローラをインスタンスに変換しようとしていますFlightRowController



  2. これが成功した場合、アニメーションAPIを使用しWKInterfaceController



    て、0.35秒でクロージャを実行します。
  3. 閉じるときに、に追加したメソッドを呼び出しますFlightRowController



    。これにより、画像の色とテーブルのこの行のセパレータが変更され、登録が完了したことを知らせる視覚的なフィードバックがユーザーに提供されます。


アプリケーションをビルドして実行します。前と同じ手順に従ってフライトに登録すると、スケジュールインターフェイスのコントローラーに戻り、テーブルの対応する行の画像とセパレーターの色が次第に新しい色に変わります。









おめでとうございます!WatchKitアニメーションの最初のセットの実装が完了しました。



ここでプロジェクトの準備例このチュートリアルで行っています。



このパートでは、2種類のWatchKitアニメーションを作成する方法を学びました。最初はアニメーション化された一連の画像をWKInterfaceController



使用し、2番目はアニメーションAPIを使用しました。



All Articles