首页 > 解决方案 > 为什么在 SwiftUI 的 TabView 中切换选项卡时 onDisappear 之后再次调用 onAppear?

问题描述

如果有任何更改,我会在出现选项卡项时调用 API。为什么在调用onDisappear 之后调用onAppear?

这是一个简单的例子:

struct ContentView: View {
    var body: some View {
        TabView {
            NavigationView {
                Text("Home")
                    .navigationTitle("Home")
                    .onAppear {
                        print("Home appeared")
                    }
                    .onDisappear {
                        print("Home disappeared")
                    }
            }
            .tabItem {
                Image(systemName: "house")
                Text("Home")
            }.tag(0)
        
            NavigationView {
                Text("Account")
                    .navigationTitle("Account")
                    .onAppear {
                        print("Account appeared")
                    }
                    .onDisappear {
                        print("Account disappeared")
                    }
            }
            .tabItem {
                Image(systemName: "gear")
                Text("Account")
            }.tag(1)
        }
    }
}    

只需运行上面的代码,我们将在 onDisappear 之后看到 onAppear。

Home appeared
---After switch tab to Account---
Home disappeared
Account appeared
Home appeared

有什么办法可以避免这种情况吗?

标签: iosswiftuitabview

解决方案


这是一个非常烦人的错误,想象一下这种情况: HomeviewonAppear方法包含一个重复获取数据的计时器。通过切换到Account视图来不可见地触发计时器。

解决方法:

  1. 为每个嵌入的NavigationView内容创建一个独立的视图
  2. @Binding将当前选择值作为参数传递给独立视图

例如:

struct ContentView: View {
    @State var selected: MenuItem = .HOME

    var body: some View {
        return TabView(selection: $selected) {
            HomeView(selectedMenuItem: $selected)
                .navigationViewStyle(StackNavigationViewStyle())
                .tabItem {
                    VStack {
                        Image(systemName: "house")
                        Text("Home")
                    }
                }
                .tag(MenuItem.HOME)
            
            AccountView(selectedMenuItem: $selected)
                .navigationViewStyle(StackNavigationViewStyle())
                .tabItem {
                    VStack {
                        Image(systemName: "gear")
                        Text("Account")
                    }
                }
                .tag(MenuItem.ACCOUNT)
        }
    }
}

enum MenuItem: Int, Codable {
    case HOME
    case ACCOUNT
}

主页视图:

struct HomeView: View {

    @Binding var selectedMenuItem: MenuItem

    var body: some View {
        return Text("Home")
            .onAppear(perform: {
                if MenuItem.HOME == selectedMenuItem {
                    print("-> HomeView")
                }
            })
    }
}

帐户视图:

struct AccountView: View {

    @Binding var selectedMenuItem: MenuItem

    var body: some View {
        return Text("Account")
            .onAppear(perform: {
                if MenuItem.ACCOUNT == selectedMenuItem {
                    print("-> AccountView")
                }
            })
    }
}

推荐阅读