当选择是可选的时,Tabview 无法更新选择?

Roo*_*kie 1 swiftui swiftui-tabview

我有以下代码片段。当我在选项卡之间滑动时,“FirstTabView”中的“selectedTab”会自动更新。但是,如果我将“selectedTab”更改为“SecondTabView”中所示的可选值,则“selectedTab”不会更新并始终显示 2。有人可以帮忙解释一下吗?

struct FirstTabView: View {
    @State private var selectedTab: Int = 2

    var body: some View {
        VStack {
            TabView(selection: $selectedTab) {
                Text("Tab 1")
                    .tag(1)
                Text("Tab 2")
                    .tag(2)
                Text("Tab 3")
                    .tag(3)
            }
            .tabViewStyle(PageTabViewStyle())
            Text(String(selectedTab))
        }
    }
}

struct SecondTabView: View {
    @State private var selectedTab: Int?

    var body: some View {
        VStack {
            TabView(selection: $selectedTab) {
                Text("Tab 1")
                    .tag(1)
                Text("Tab 2")
                    .tag(2)
                Text("Tab 3")
                    .tag(3)
            }
            .tabViewStyle(PageTabViewStyle())
            Text(String(selectedTab ?? 2))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我创建一个新的非可选变量来绑定选择,然后“selectedTab”可以再次自动更新。但我检查了 SwiftUI 文档,选项卡视图确实接受可选值作为选择参数。

struct SecondTabView: View {
    @State private var selectedTab: Int?
    
    var tabBinding: Binding<Int> {
        Binding(
            get: { selectedTab ?? 2 },
            set: { selectedTab = $0 }
        )
    }

    var body: some View {
        VStack {
            TabView(selection: $tabBinding) {
                Text("Tab 1")
                    .tag(1)
                Text("Tab 2")
                    .tag(2)
                Text("Tab 3")
                    .tag(3)
            }
            .tabViewStyle(PageTabViewStyle())
            Text(String(selectedTab ?? 2))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Swe*_*per 6

tag选择的类型必须与您为选项卡提供的 s的类型完全匹配。

您正在Int为选项卡提供标签,但选择的类型是Int?,因此选择值不会更新。SwiftUI 无法设置任何Int?值,使其等于(通过使用==所需的运算符Equatable)不可为 null 的Int“1”。毕竟Equatable只能比较同类型的东西。

请注意,尽管您通常可以比较Int和 ,Int?因为作为一种语言功能,您可以在需要可选值的地方编写非可选值。SwiftUI 的内部没有这个“功能”。

如果您想使用可选类型作为选择值,请将标签也设置为可选:

Text("Tab 1")
    .tag(1 as Int?) // also can be written as Optional.some(1)
Text("Tab 2")
    .tag(2 as Int?)
Text("Tab 3")
    .tag(3 as Int?)
Run Code Online (Sandbox Code Playgroud)

也就是说, 的初始值selectedTabnil,并且没有带有标签的选项卡nil,因此(至少在我的测试中)最初选择了第一个选项卡(但不会将选择值更改为 1)。

所以我不确定为什么在这种情况下要使用可选选择值。事实上,我想不出它有什么用处。如果您想要一个“默认”选项卡,只需初始化selectedTab为其中一个标签即可。

但我检查了 SwiftUI 文档,选项卡视图确实接受可选值作为选择参数。

您可能已经发现了这个

init(
    selection: Binding<SelectionValue>?,
    @ViewBuilder content: () -> Content
)
Run Code Online (Sandbox Code Playgroud)

Binding<SelectionValue>?不是可选值的绑定,可以写成Binding<SelectionValue?>. 它是一个可选的绑定,即它允许您编写:

TabView(selection: nil) { ... }
Run Code Online (Sandbox Code Playgroud)

因此,当您传递您的$selectedTab,即 a 时Binding<Int?>,选项卡视图的SelectionValueis Int?,它会查找类型为 的标签Int?