LoginSignup
3
2

SwiftUI Tutorials②: Building lists and navigationでSwiftUIを初めてみよう!

Last updated at Posted at 2023-11-03

SwiftUI Tutorials

Apple公式が出しているSWiftUIのチュートリアルです!
今回は「リストとナビゲーションを構築する」というチュートリアルのリストの作成とナビゲーションの設定でつまずいたところを共有します!

Listの作成 (静的リスト作成・動的リスト作成)

SwiftUIのList型を使うとき、プラットフォーム固有のビューのリストを表示できる。リストの要素は、これまでに作成したスタックの子ビューのように静的であることも、動的に生成されることもできる。

静的リスト作成

静的 = 「変化しないもの」
List一覧が生成されます!リストの要素を個別に指定する!

LandmarkList.swift
 import SwiftUI
 
 struct LandmarkList: View {
     var body: some View {
         List {
             LandmarkRow(landmark: landmarks[0])
             LandmarkRow(landmark: landmarks[1])
         }
     }
 }
 
 #Preview {
     LandmarkList()
 }

下記のように、リストに入っているのは2つという限られた個数であるため、リストの要素を個別に指定し、値をJSON形式のファイルから取得することができます!
4a32a57be1cdeb25f9468ffbc37b1df3.png

動的リスト作成

動的 = 「変化するもの」
リストは識別可能なデータで動作する!
データを識別可能にするには、次の2つの方法がある!

① 各要素を一意に識別するプロパティへのキーパスをデータと一緒に渡す方法

② データ型をIdentifiableプロトコルに準拠させる方法

① 各要素を一意に識別するプロパティへのキーパスをデータと一緒に渡す方法

キーパスであるid: .idとデータであるlandmarksを一緒に渡している!

LandmarkList.swift
import SwiftUI

struct LandmarkList: View {
    var body: some View {
        List(landmarks, id: \.id) { landmark in
            LandmarkRow(landmark: landmark)
        }
    }
}

#Preview {
    LandmarkList()
}

② データ型をIdentifiableプロトコルに準拠させる方法

Identifiable「識別可能」
Identifiableプロトコルに準拠した構造体は、idを割り振ることができるということ。
idが振られることでSwiftUI側はどのコンテンツのデータを更新すればいいのかがわかる。

Landmark.swift
struct Landmark: Hashable, Codable, Identifiable {
    var id: Int
    var name: String
    var park: String
    var state: String
    var description: String
    private var imageName: String

    var image: Image {
        Image(imageName)
    }
 
    private var coordinates: Coordinates
    var locationCoordinate: CLLocationCoordinate2D {
        CLLocationCoordinate2D(latitude: coordinates.latitude,
                               longitude: coordinates.longitude)
    }
    struct Coordinates: Hashable, Codable {
        var latitude: Double
        var longitude: Double
    }
}

※もし、Identifiableプロトコルに準拠させないと、下記のようなエラーになるので注意!
エラー:Initializer 'init(_:rowContent:)' requires that 'Landmark' conform to 'Identifiable'
配列の要素を一意に識別できるキー値がないため、配列の値を取り出すことができない

LandmarkList.swift
import SwiftUI

struct LandmarkList: View {
    var body: some View {
        List(landmarks) { landmark in
            LandmarkRow(landmark: landmark)
        }
    }
}

#Preview {
    LandmarkList()
}

①と②どちらの方法でも以下のようなViewが作成される!
ef100129cbb3b2cbe09cfc09df60af5c.png

Navigation

NavigationSplitView

NavigationSplitViewは、ビューを2列または3列で表示するビューで、先頭の列での選択が後続の列での表示を制御する。

ナビゲーションスプリットビューは、選択した後に表示されるビューのプレースホルダとなる2番目の入力を受け取る。iPhoneの場合、スプリットビューにプレースホルダは必要ありませんが、iPadの場合、誰かが選択する前に詳細ペインを表示することができる。

NavigationSplitViewを使って画面構築をした時、
iPhoneやApple Watchなどの狭いサイズのデバイスの場合、ナビゲーションの分割ビューが1つのスタックに折りたたまれたコンパクトカラムとして構成される!

iPadの場合、詳細を選択する前にすでに2分割になっているリストビューが表示されている。detailの後に記述が必要になる!
2列(カラム)のレイアウトが表示される!

NavigationLink

NavigationLinkとは、ナビゲーション・プレゼンテーションを制御するビュー

ナビゲーションリンクをタップすると、NavigationStackまたはNavigationSplitView内のビューが表示される!リンクのラベルクロージャにビューコンテンツを提供することで、リンクの視覚的な外観を制御できます。例えば、Labelを使ってリンクを表示することができる!

LandmarkList.swift
import SwiftUI

struct LandmarkList: View {
    var body: some View {
        NavigationSplitView {

            List(landmarks) { landmark in
                NavigationLink {
                    //②詳細説明へ遷移
                    LandmarkDetail(landmark: landmark)
                } label: {
                    //①リスト行のリンクを押すと、
                    LandmarkRow(landmark: landmark)
                }
            }
            .navigationTitle("Landmarks")
        } detail: {
            //iPadの場合表示
            Text("Select a Landmark")
        }
    }
}

#Preview {
    LandmarkList()
}

①リスト行のリンクを押すと、②詳細説明へ遷移することができました!

15e0f25dab32545ef3e14d3a496736ec.gif

参考文献

3
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2