v1はこちら

v2 Building lists and navigation リストとナビゲーション

こちらを進めます!
section 1 Create a landmark model ランドマーク一覧のデータですね
チュートリアルのプロジェクトをダウンロードして
Resources の landmarkData.json を使います。
プロジェクトは、v1の続きを使います。
Landmarksの下にResources グループを作成、そこにjsonを追加

Resourcesディレクトリにjsonファイルを入れました。
Copy items if neededをチェックしてFinish

landmarkDataが入りました。
File > New > File. ..
Swift Fileを作ります
Landmark.swiftです。ランドマークアイテム用ですね

サンプルからランドマークのjpgをAssetsに入れます
一つ前のturtlerockも含めてimagesディレクトリをそのままAssetsに入れました

import Foundation import SwiftUI import CoreLocation struct Landmark : Hashable, Codable { var id: Int var name: String var park: String var state: String var desctiption: String private var imageName: String // SwiftUIが必要 var image: Image { Image(imageName) } private var coordinates: Coordinates // CoreLocationが必要 var locationCoordinate: CLLocationCoordinate2D { CLLocationCoordinate2D( latitude: coordinates.latitude, longitude: coordinates.longitude) } struct Coordinates: Hashable, Codable{ var latitude: Double var longitude: Double } }
import SwiftUI も見慣れそうですね^^
Imageを呼び出すプロパティ追記です
位置情報、Coordinatesを作って。
ところで Hashable, Codable ? の意味をここで見ておきましょう
Hashable
ハッシュ化できるということのようです、要素として取り回すときは必要?そうです
Codable
コード化できるということで、たとえばjsonにエンコード、デコードできるようになるようです!
なるほどですね
ModelData.swift を作成。モデル、json読み出しの関数も自分で書くようです?
import Foundation var landmarks: [Landmark] = load("landmarkData.json") func load<T: Decodable>(_ filename: String) -> T { let data: Data guard let file = Bundle.main.url(forResource: filename, withExtension: nil) else { fatalError("Couldn't find \(filename) in main bundle.") } do { data = try Data(contentsOf: file) } catch { fatalError("Couldnt load \(filename) from main bundle:\n\(error)") } do { let decoder = JSONDecoder() return try decoder.decode(T.self, from: data) } catch { fatalError("Couldnt load \(filename) as \(T.self):\n\(error)") } }
load関数、テンプレート(ジェネリック)やら例外処理やら初めてでも勉強になりますね
ファイルをグループ化する、View, Model, Resources と

section 2 create row view 列ビューを作成
swiftUI view で LandmarkRow.swift を作成
import SwiftUI struct LandmarkRow: View { var landmark: Landmark var body: some View { HStack { Text(landmark.name) } } } #Preview { LandmarkRow(landmark: landmarks[0]) }
preview のところのコンストラクタで モデルで作成した var landmarks を使用して landmarks[0]を利用
HStack横並び。landmark.nameで名前表示
json読み込みエラー!!!Landmarkの変数名を間違えて jsonにない文字だったのでエラーに…

画像を読み込み、サイズしてして、Spacerで左寄せに
section 3 row previewをカスタマイズ
カスタマイズって日本語で?個別化、特注と書いてありました。
プレビューを切り替え
2つpreviewを置くと上で切り替え、名前もつけられると

Groupを使うと2つ並びました
section 4 リストを作ろう!
SwiftUI View で LandmarkList.swiftを作成

List に LandmarkRowを並べるだけで…wow
section 5 データを読み込んでリスト表示
list を landmarksから読むだけで、すべてリストに表示されました

struct Landmark : Hashable, Codable, Identifiable { var id: Int
Landmarkに Identifiableプロトコルを追加
id で一意になるそうです。同じidがあったらエラーになるのかな?特に重複チェックなどそういうものではないようです
最初は idを指定していましたが List(landmarks, id: \.id) { Identifiableを使うと idは自動でid認識されるということのような List(landmarks) {
section 6 一覧と詳細のナビゲーション
swiftui view作成 LandmarkDetail.swift
内容は前回作成したContentViewをそのままコピー

ContentViewは LandmarkListに変更
トップをこのリストの状態に
NavigationSplitViewを入れて
Listの中を NavigationLinkと labelを設定するとLandmarkDetail に遷移できました

リストからの詳細、詳細からリストが出来ました◎
section 7 Pass data into child views 各ビューにデータを渡します
名前と画像と位置情報
CircleImageには var image で呼び出すとき CircleImage(image: Image(…))
MapView には var coordinate: CLLocationCoordinate2D を追加して MapView(coordinate: … )
Mapの呼び出しは Map(position: .constant(.region(region))) と データ変更で切り替わる形に
LandmarkDetailには var landmark:Landmark で呼び出しは LandmarkDetail(landmark: …)で
各所 渡したデータを利用するように変更していきます。
LandmarkDetailは VStackを ScrollViewに変更しました。
すると詳細が長文で切れているところがスクロールで表示できるようになりました
section 8 機種ごとのプレビューを表示?
iPadに変更してみると

表示がタイトルだけになりました select a landmarkだけに

iPad 左上の青っぽいツールバーアイコンを押すと左にリストが表示されます

これが NavigationSplitView ということですね

ここで横向きに出来たりします
ダイブできる感ありますね^^
Check Your Understanding
Great job, you’ve answered all the questions for this tutorial.
無事終わりました。選択肢の英語難しい…英語の意味がわからんですね^^;;;;
超簡単な英語だとは思うのですが基本が難しい…
次はユーザー入力操作

コメント