スクリーンショット_2020-01-24_17

【Xcode】超初心者のためのSwiftUIチュートリアル9

Apple公式のSwiftUIチュートリアルを、プログラミング超初心者向けに優しく解説するシリーズ第9回。引き続き「Handling User Input(ユーザー入力の処理)」を進めていきます。
前の第8回セクション3では、表示するランドマークの切り替えができるようになりました。今回はお気に入りのランドマークをユーザーが自由に変更できる機能を付け加えていきます。

Appleの公式チュートリアルはこちらを参照してください。日本語で閲覧したい場合は、自動翻訳機能のあるGoogleChromeなどのブラウザを使用するといいでしょう。

1.今回の作業の概略

前回までは、お気に入りのランドマークはデータソースで決まっていて変更できませんでした。そこでお気に入りのランドマークをユーザーが自由に選べるように改造していきます。作業の過程をざっくり説明すると、

・お気に入り(true)か否(false)かを仕分けるフィルタ(UserData)を作成
・landmarkDataをUserData経由で取得するよう各ファイルを書き換える
・詳細画面(LandmarkDetail)にお気に入りの切り替えボタンを設定
・ボタンで選んだ値をUserDataフィルタ経由で各ファイルに渡すようにする

という流れです。アプリの動きとしては、下の図のようになります。

画像9

それでは順番に作っていきましょう。

2.セクション4/UserData.swiftファイルを作成する

まず新しいSwiftファイルUserData.swiftを作成します。あらかじめ入っているコードを削除して、下のようにフレームワークとクラスを定義しましょう。

import SwiftUI
import Combine  //値を監視して仕分けや型の変更を行えるフレームワーク

final class UserData: ObservableObject  {  //Combineフレームワークで扱える型に値を変更するクラス

}

UserDataは、値をフィルタリングする役割を果たします。ここでは「お気に入りのランドマーク」と「そうではないランドマーク」を仕分けるのに使います。

※以下の説明は、よく分からなければ飛ばしても大丈夫です。
CombineはSwiftで用意された新しいフレームワーク(機能の枠組み)のひとつです。ざっくり言うと、値を監視してフィルタリングや必要な形に加工する処理などを行えます。
UserDataクラスのObservableObjectは、扱う変数をCombineで監視できる値に変換する型です。
処理のためにいったん変換された値は、それぞれのビューファイルでenvironmentObject(_:)という修飾子をつけた形で渡されて使えるようになります。

次はクラスの中に2つの変数を追加します。これは前にも出てきましたね。

var showFavoritesOnly = false
var landmarks = landmarkData

それぞれの変数の先頭に@Publishedを追加してください。@Publishedをつけると、変数の値をCombineで監視できるようになります。
下のように書けたら次に進みましょう。

スクリーンショット 2020-01-26 8.21.39


3.セクション5/LandmarkList.swiftを書き換える

ここから各ファイルごとに、値やデータをUserData経由で読み込む形に書き換えていきます。
LandmarkList.swiftに戻り(LandmarkDetail.swiftではないので注意)、@State var showFavoritesOnly = false の部分を下記のコードに書き換えます(赤線部分のようになります)。EnvironmentObjectとは、UserDataでフィルタリング済の値のことです。

 @EnvironmentObject var userData: UserData //userDataでフィルタリング済の値

スクリーンショット 2020-01-24 15.17.14

さらにプレビュー設定のlandmarkList()の下に、次の1行を付け加えます。
これでプレビューにもフィルタリング済の値が入って表示されます。

.environmentObject(UserData()) //userDataでフィルタリングされた値を示す

スクリーンショット 2020-01-27 16.00.10

他の部分も下図のように書き換えていきましょう。

スクリーンショット 2020-01-24 15.51.12

これでそれぞれの値をUserDataを経由して受け取る形になりました。

4.SceneDelegate.swiftを書き換える

続いてSceneDelegate.swiftにも下記の部分に追記します。

スクリーンショット 2020-01-24 16.09.47

.environmentObject(UserData()) //userDataでフィルタリングされた値を示す


5.LandmarkDetail.swiftを書き換える

SceneDelegate.swiftが終わったら、LandmarkDetail.swiftにも追記していきます。

先頭部分は赤で示した部分を追記します。下はサンプルコードです。

スクリーンショット 2020-01-24 16.29.08

import SwiftUI

struct LandmarkDetail: View {
   @EnvironmentObject var userData: UserData 
      
   var landmark: Landmark

   var landmarkIndex: Int {
       userData.landmarks.firstIndex(where: { $0.id == landmark.id })!
   }

プレビュー設定の部分は赤ラインの1行を追記してください。

スクリーンショット 2020-01-24 16.29.22

.environmentObject(UserData())

これでビューファイルからUserData.swiftのデータを参照できるようになりました。この段階でいったんライブプレビューにして、変更後も正しく動作しているか確認してみましょう。

スクリーンショット 2020-01-24 16.28.34

正しく動作するのが確認できたら、次はランドマークの詳細画面にお気に入りを選ぶボタンを作っていきます。


6.セクション6/詳細画面にボタンを設定する

今度は詳細画面にボタン機能を持つスターを表示します。スターをタップすることでお気に入りのランドマークを変更できるようにしましょう。

スクリーンショット 2020-01-25 0.26.56

下はボタン部分のサンプルコードです。

HStack {
    Text(landmark.name)
       .font(.title)

    //「お気に入り」を決めるボタンのアクション	
    Button(action: {
    self.userData.landmarks[self.landmarkIndex].isFavorite.toggle()
	    
    }) {
        if self.userData.landmarks[self.landmarkIndex].isFavorite {
            Image(systemName: "star.fill")
                .foregroundColor(.yellow)
	} else {
	    Image(systemName: "star")
	        .foregroundColor(.gray)
	}
    }
}

ボタンができたらLandmarkList.swiftに戻って、ライブプレビューモードにして動きを確認します。

リストから詳細画面を表示して、スター部分をタップします。「お気に入り」のときは黄色いスター、そうでない時はグレーのスターです。

画像11

左上の「< LandmarkList」をタップするとリストに戻り、詳細画面でお気に入り指定した行のスターが黄色に変わっています(このあたりは動画で見られるチュートリアルの方がわかりやすいですね)。
トグルをタップしてお気に入りだけを表示しても、先ほど選んだランドマークがお気に入りとして表示されたらOKです。

うまくできたでしょうか。次からは新しい「Drawing Paths and Shapes(パスとシェイプの描画)」に入ります。

関連記事は下のマガジンをご覧ください。



この記事が気に入ったらサポートをしてみませんか?