【问题标题】:How to pop to specific view in the TabView Application in swiftui. I used StackNavigation also but not working in swiftui如何在 swiftui 中弹出到 TabView 应用程序中的特定视图。我也使用了 StackNavigation 但不在 swiftui 中工作
【发布时间】:2021-12-04 06:43:33
【问题描述】:

我在弹出特定视图时遇到问题。让我解释一下层次结构。

ContentView -> 2 个选项卡,TabAView 和 TabBView TabBView 内部。有 1 个视图使用 ConnectView:连接按钮在哪里。点击连接按钮后,用户移动到另一个视图,称为 UserAppView。从这里用户可以检查他的个人资料并更新。 Update API 调用后,需要从 UserFirstFormView 弹出到 UserAppView。

这是更好地理解我的问题的代码。

ContentView.swift

struct ContentView: View {
    enum AppPage: Int {
        case TabA=0, TabB=1
    }
    
    @StateObject var settings = Settings()
    @ObservedObject var userViewModel: UserViewModel
    
    var body: some View {
        NavigationView {
            TabView(selection: $settings.tabItem) {
                TabAView(userViewModel: userViewModel)
                    .tabItem {
                        Text("TabA")
                    }
                    .tag(AppPage.TabA)
                
                TabBView(userViewModel: userViewModel)
                    .tabItem {
                        Text("Apps")
                    }
                    .tag(AppPage.TabB)
            }
            .accentColor(.white)
            .edgesIgnoringSafeArea(.top)
            .onAppear(perform: {
                settings.tabItem = .TabA
            })
            .navigationBarTitleDisplayMode(.inline)
        }
        .environmentObject(settings)
    }
}

这是 TabAView:

 struct TabAView: View {
    
    @ObservedObject var userViewModel: UserViewModel
    @EnvironmentObject var settings: Settings
    
    init(userViewModel: UserViewModel) {
        self.userViewModel = userViewModel
    }
    
    var body: some View {
        Vstack {
            /// code
        }
        .onAppear(perform: {
            /// code
        })
        .environmentObject(settings)
    }
}

这是另一个 TabBView:

struct TabBView: View {
    
    @ObservedObject var userViewModel: UserViewModel
    
    init(userViewModel: UserViewModel) {
        self.userViewModel = userViewModel
    }
    
    var body: some View {
        VStack (spacing: 10) {
            NavigationLink(destination: ConnectView(viewModel: ConnectViewModel(id: id!), userViewModel: userViewModel)) {
                UserCardWidget()
            }
        }
    }
}

在 TabBView 上使用了 1 个 connectView,用户将通过该 connectView 进行连接。此处使用 ConnectViewModel 调用连接 API。

class ConnectViewModel: ObservableObject {
    
    var id: String?
    
    init(id: String) {
        self.id = id
    }
    
    func connect(completion: @escaping () -> Void) {
        APIService.shared.connectApp(id: self.id!) { connected in
            DispatchQueue.main.async {
                self.isConnected = connected ?? false
                completion()
            }
        }
    }
}

这是连接视图

struct ConnectView: View {
    
    @ObservedObject var connectViewModel: ConnectViewModel
    @ObservedObject var userViewModel: UserViewModel
    @State var buttonTitle = "CONNECT WITH THIS"
    @State var isShowingDetailView = false
    
    var body: some View {
        VStack {
            Spacer()
            if let id = connectViewModel.id {
                NavigationLink(destination: UserAppView(id: id, userViewModel: userViewModel), isActive: $isShowingDetailView) {
                    Button(buttonTitle, action: {
                        connectViewModel.connect {
                            buttonTitle = "CONNECTED"
                            isShowingDetailView = true
                        }
                    })
                }
            }
        }
    }
}

这是调用 API 以获取一些与用户相关的详细信息的 UserAppViewModel:

类 UserAppViewModel: ObservableObject {

var id = ""
func getdetails() {
    APIService.shared.getDetails() { userDetails in
        DispatchQueue.main.async {
            /// code
        }
    }
}

}

这是 UserAppView 类

struct UserAppView: View {
    
    @ObservedObject var userViewModel: UserViewModel
    @State private var signUpInButtonClicked: Bool = false
    @StateObject private var userAppViewModel = UserAppViewModel()

    init(id: String, userViewModel: UserViewModel) {
        self.id = id
        self.userViewModel = userViewModel
    }
    
    var body: some View {
        
        VStack {
            Text(userAppViewModel.status)
            VStack {
                Spacer()
                NavigationLink(
                    destination: ProfileView(userAppViewModel: userAppViewModel, isActive: $signUpInButtonClicked)) { EmptyView() }
                if /// Condition  {
                    Button(action: {
                        signUpInButtonClicked = true
                    }, label: {
                        ZStack {
                            /// code
                        }
                        .frame(maxWidth: 77, maxHeight: 25)
                    })
            }
            
        }.onAppear(perform: {
            **userAppViewModel.getDetails**(id: id)
            
        })
    }
}

从这里,用户可以导航到 ProfileView。

struct ProfileUpdateView: View {
    
    @State private var navigationSelectionFirstFormView = false
    @State private var navigationSelectionLastFormView = false
    
    public var body: some View {
        VStack {
            NavigationLink(destination: UserFirstFormView(userAppViewModel: userAppViewModel), isActive: $navigationSelectionFirstFormView) {
                EmptyView()
            }
            NavigationLink(destination: UserLastFormView(userAppViewModel: userAppViewModel), isActive: $navigationSelectionLastFormView) {
                EmptyView()
            }
        }
        .navigationBarItems(trailing:  Button(action: {
            if  Condition {
                navigationSelectionFirstFormView = true
            } else {
                navigationSelectionLastFormView = true
            }
        }, label: {
            HStack {
                Text("Action")
                    .foregroundColor(Color.blue)
            }
        })
        )
    }

}

此外,他们的用户将移至下一个屏幕以更新个人资料。

struct UserFirstFormView: View {
    var body: some View {
        VStack {
            /// code
            ///
            Button("buttonTitle", action: {
                API Call completion: { status in
                    if status {
                        self.rootPresentationMode.wrappedValue.dismiss()
                    }
                })
            })
                .frame(maxHeight: 45)
        }
    }
}

一旦收到 API 响应,我会尝试从该视图中弹出,但没有任何效果。

出于机密的考虑,我已删除了大部分代码,但此代码将解释原因和错误。请查看代码并帮助我。

【问题讨论】:

    标签: swiftui environment-variables navigationview tabview swiftui-navigationlink


    【解决方案1】:

    您可以将导航链接与标签:和选择:重载一起使用,并让视图模型控制打开的链接,这里是一个示例

    enum profileViews {
    case view1
    case view2}
    

    在您的 viewModel 中添加一个已发布的变量来保存活动视图

     @Published var activeView: profileViews?
    

    然后在您的导航链接中,您可以这样做

    NavigationLink(
                destination: secondView(profileViewModel: ProfileViewModel ),
                tag: profileViews.view1,
                selection: self.$profileViewModel.activeView
            ){}
    

    然后你可以弹出任何视图,只需更新视图模型中的变量

    self.profileViewModel.activeView = nil
    

    【讨论】:

    • 如果这个视图模型会被大量使用,也许单例或环境对象可以更好地帮助你,而不是传递视图模型的引用。
    • 是的,从UserAppView来看,这个模型用在7个视图中。
    • 我没有观察这个 UserAppViewModel,我在 UserAppView 中创建了 StateObject。我已经编辑了这个问题。即使在 activeView 为零后视图也不会弹出。 :(
    • 我没有观察这个 UserAppViewModel,我在 UserAppView 中创建了 StateObject,然后在后续视图中观察
    猜你喜欢
    • 1970-01-01
    • 2022-06-17
    • 2022-01-21
    • 2022-06-23
    • 1970-01-01
    • 2020-04-20
    • 2020-02-19
    • 1970-01-01
    • 2020-09-10
    相关资源
    最近更新 更多