SwiftUI TabView:如何检测选项卡上的点击?

Dan*_*e B 16 tabview swift swiftui swiftui-tabview swiftui-ontapgesture

我想在每次点击选项卡时运行一个函数。

在下面的代码中(通过使用onTapGesture),当我点击新选项卡时,myFunction会被调用,但选项卡视图不会更改。

struct DetailView: View {
    var model: MyModel
    @State var selectedTab = 1
    
    var body: some View {
        TabView(selection: $selectedTab) {
            Text("Graphs").tabItem{Text("Graphs")}
               .tag(1)
            Text("Days").tabItem{Text("Days")}
               .tag(2)
            Text("Summary").tabItem{Text("Summary")}
               .tag(3)
        }
        .onTapGesture {
            model.myFunction(item: selectedTab)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能得到这两件事:

  • tabview正常显示
  • 我的函数被调用

Joe*_*Joe 15

从 iOS 14 开始,您可以使用onChange它在状态变量更改时执行代码。您可以将点击手势替换为:

.onChange(of: selectedTab) { newValue in
    model.myFunction(item: newValue)
}
Run Code Online (Sandbox Code Playgroud)

如果您不想受限于 iOS 14,您可以在此处找到其他选项:状态更改时如何运行操作?

  • 这仅在选择不同选项卡时调用该函数,但在点击同一选项卡时不会调用该函数。 (13认同)

小智 14

除一种情况外,上述答案都有效。如果您位于同一选项卡中,则不会调用 .onChange()。更好的方法是创建绑定扩展

extension Binding {
    func onUpdate(_ closure: @escaping () -> Void) -> Binding<Value> {
        Binding(get: {
            wrappedValue
        }, set: { newValue in
            wrappedValue = newValue
            closure()
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

用法会是这样的

TabView(selection: $selectedTab.onUpdate{ model.myFunction(item: selectedTab) }) {
        Text("Graphs").tabItem{Text("Graphs")}
           .tag(1)
        Text("Days").tabItem{Text("Days")}
           .tag(2)
        Text("Summary").tabItem{Text("Summary")}
           .tag(3)
    }
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案——它很优雅,并且与 SwiftUI 工作范式相协调。请注意,可以将“oldValue”和“newValue”的参数添加到“onUpdate”闭包中。 (2认同)