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: IntLandmarkに 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.
無事終わりました。選択肢の英語難しい…英語の意味がわからんですね^^;;;;
超簡単な英語だとは思うのですが基本が難しい…
次はユーザー入力操作






コメント