ひとしれずひっそり

主にソフトに関することをメモしていきます。過程をそのまま書いていたりするので間違いが含まれます。鵜呑みしない様に。

NavigationLink

NavigationViewのリンク

NavigationViewはdeprecatedになって NavigationStack か NavigationSplitView を使うという事らしい。(iOS 16から)

developer.apple.com

最初のブロックはリンク先となるViewを指定する。
labelのブロックではcellの中身を指定する。
Lableが使えて、従来のUITableViewCellっぽい事ができそう。

NavigationLink {
    // ここはリンク先のViewを指定
    FolderDetail(id: workFolder.id)
} label: {
    // cellの中身
    Label("Work Folder", systemImage: "folder")
}

CoreDataを使ったアプリではリンク先にTextを使用していて、テキストが表示されるViewが表示される。

NavigationLink {
    Text("Item at \(item.timestamp!, formatter: itemFormatter)")
} label: {
    Text(item.timestamp!, formatter: itemFormatter)
}

Imageを指定すれば画像になるのか?

表示された。

cellに表示するのがテキストのみの場合はNavigationLink()の引数としてテキストを渡して使用できる。

NavigationLink("Work Folder") {
    FolderDetail(id: workFolder.id)
}

struct ColorDetail: View {
    var color: Color

    var body: some View {
        color.navigationTitle(color.description)
    }
}

これを表示するとこんな感じになる。

color.navigationTitle(color.description) でタイトルを表示していると思うが、colorを指定している時点で色がつくのか?

var body: some View {
    color
}

これで色がついてる。なるほどColor自体がViewの扱いになるのか。

リンクからの呼び出し。

NavigationStack {
    List {
        NavigationLink("Mint") { ColorDetail(color: .mint) }
        NavigationLink("Pink") { ColorDetail(color: .pink) }
        NavigationLink("Teal") { ColorDetail(color: .teal) }
    }
    .navigationTitle("Colors")
}

これをこの様に書けるという事らしい。

NavigationStack {
    List {
        NavigationLink("Mint", value: Color.mint)
        NavigationLink("Pink", value: Color.pink)
        NavigationLink("Teal", value: Color.teal)
    }
    .navigationDestination(for: Color.self) { color in
        ColorDetail(color: color)
    }
    .navigationTitle("Colors")
}

NavigationLinkでvalueとして色を渡しておいて、クリックされた時にそのvalueがnavigationDestinationに渡ってきてここでリンク先のViewを指定している様だ。


空のcolorsを用意して、それに追加した時に画面遷移できる。
予めCellを用意していなくてもプログラムで遷移させる事ができる様になる。

struct SomeView: View {
    @State private var colors: [Color] = []
    var body: some View {
        NavigationStack(path: $colors) {
            List(colors, id:\.self) { color in
                NavigationLink(color.description, value: color)
            }

            .navigationDestination(for: Color.self) { color in
                ColorDetail(color: color)
            }
        }
        Button {
            showBlue()
        } label: {
            Text("Blue")
        }

    }
    func showBlue() {
        colors.append(.blue)
    }
}

戻る時にCellが一瞬表示されるのでheightを0にしておけば見えなくなった。

List(colors, id:\.self) { color in
    NavigationLink(color.description, value: color)
}
.frame(height: 0)

NavigationSplitViewも同様。
selectionを使用した場合はselectionをプログラムで変更すると画面遷移する。

struct SomeView: View {
    @State private var colors: [Color] = [.mint, .pink, .teal]
    @State private var selection: Color? // Nothing selected by default.

    var body: some View {
        NavigationSplitView {
            List(colors, id: \.self, selection: $selection) { color in
                NavigationLink(color.description, value: color)
            }
        } detail: {
            if let color = selection {
                ColorDetail(color: color)
            } else {
                Text("Pick a color")
            }
        }
        Button {
            showBlue()
        } label: {
            Text("Blue")
        }
        Button {
            showNil()
        } label: {
            Text("Null")
        }
    }
    func showBlue() {
        selection = Color.blue
    }
    func showNil() {
        selection = nil
    }
}

nilの場合の表示が確認できないと思ったがiPadで横向きにしないと確認できなかった。

if let という書き方ができるのか。勉強になった。