3

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

当我点击一个新选项卡时,在下面的代码中(通过使用onTapGesturemyFunction被调用,但选项卡视图没有改变。

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)
        }
    }
}

我怎样才能得到这两个东西:

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

3 回答 3

9

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

        .onChange(of: selectedTab) { newValue in
            model.myFunction(item: newValue)
        }

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

于 2020-11-03T03:08:32.860 回答
1

这是可能的方法。对于 TabView,它提供与点击另一个选项卡并返回相同的行为,因此具有持久的外观和感觉。

gif图片

完整的模块代码:

import SwiftUI

struct TestPopToRootInTab: View {
@State private var selection = 0
@State private var resetNavigationID = UUID()

var body: some View {

    let selectable = Binding(        // << proxy binding to catch tab tap
        get: { self.selection },
        set: { self.selection = $0

            // set new ID to recreate NavigationView, so put it
            // in root state, same as is on change tab and back
            self.resetNavigationID = UUID()
        })

    return TabView(selection: selectable) {
        self.tab1()
            .tabItem {
                Image(systemName: "1.circle")
            }.tag(0)
        self.tab2()
            .tabItem {
                Image(systemName: "2.circle")
            }.tag(1)
    }
}

private func tab1() -> some View {
    NavigationView {
        NavigationLink(destination: TabChildView()) {
            Text("Tab1 - Initial")
        }
    }.id(self.resetNavigationID) // << making id modifiable
}

private func tab2() -> some View {
    Text("Tab2")
}
}

struct TabChildView: View {
    var number = 1
    var body: some View {
        NavigationLink("Child \(number)",
                       destination: TabChildView(number: number + 1))
    }
}

struct TestPopToRootInTab_Previews: PreviewProvider {
    static var previews: some View {
        TestPopToRootInTab()
    }
}
于 2021-09-15T11:03:50.500 回答
1

除了在一种情况下,上述答案效果很好。如果您出现在同一个选项卡中,则不会调用 .onChange()。更好的方法是创建绑定的扩展

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

用法会是这样的

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)
    }
于 2021-12-30T09:30:44.527 回答