如何在 swiftui 中弹出到 TabView 应用程序中的特定视图。我也使用了 StackNavigation 但不在 swiftui 中工作

Posted

技术标签:

【中文标题】如何在 swiftui 中弹出到 TabView 应用程序中的特定视图。我也使用了 StackNavigation 但不在 swiftui 中工作【英文标题】:How to pop to specific view in the TabView Application in swiftui. I used StackNavigation also but not working in 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 响应,我会尝试从该视图中弹出,但没有任何效果。

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

【问题讨论】:

【参考方案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,然后在后续视图中观察

以上是关于如何在 swiftui 中弹出到 TabView 应用程序中的特定视图。我也使用了 StackNavigation 但不在 swiftui 中工作的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:再次轻按选定的选项卡时,弹出到根视图

如何在颤动中弹出到特定屏幕

在导航控制器中弹出到根视图

如何在 SwiftUI 中将 TabView 与 NavigationView 一起使用?

在 ios 中弹出到下一个 viewController

如何在 TabView SwiftUI 中保存视图的列表状态