从SwiftUI视图返回到UIViewController的方法是什么?

3

我在所有视图中都使用SwiftUI 1.0,从主视图开始,它是除登录界面外的主屏幕,因为我正在使用客户端LoginSDK,该SDK是通过UIKit创建的。

因此,在LoginViewController中,我可以使用以下代码在成功登录后推送MainView():

func showMainView() {
    let host = UIHostingController(rootView: MainView())
    self.navigationController?.navigationBar.isHidden = true
    self.navigationController?.pushViewController(host, animated: true)
}

在MainView中,我尝试实现一个注销方法,当用户点击注销按钮时将LoginViewController设置为根视图,代码如下:
struct MainView: View {
    
    var body: some View {
            NavigationView {
                    VStack {
                        Button(action: {
                           logout()
                        }, label: {
                            Image("Logout")
                                .resizable()
                                .frame(width: 20, height: 16)
                        })
                    }
            }
    }

  //Method to logout and set the RootNavigationViewController as rootViewController
  func logout () {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    //The LoginViewController is embedded in RootNavigationViewController
    let rootViewController = storyboard.instantiateViewController(withIdentifier: "RootNavigationViewController") as! UINavigationController
            
    if let window = UIApplication.shared.windows.first {
        window.rootViewController = rootViewController
        window.endEditing(true)
        window.makeKeyAndVisible()
    }
  }

}

以上的注销方法实现并没有做任何事情。我想知道如何从MainView(一个SwiftUI结构)导航回登录视图控制器(一个UIKit UIViewController)。

尝试呈现而不是强行推销观点。另外,你可以使用绑定来显示/隐藏视图。 - undefined
@Rj19,谢谢你的回答,但业务需求是从LoginViewController推送MainView。另外,关于显示和隐藏视图,你是否已经尝试过使用UIKit的UIViewController和SwiftUI的view?如果是的话,能否提供一些代码参考。谢谢! - undefined
我用Binding来实现显示和隐藏,因为它非常简单和富有表现力。不过,你的情况可能会有些不同。这是链接:https://swiftwithmajid.com/2020/04/08/binding-in-swiftui/ - undefined
2个回答

1
可能的解决方案是使用回调函数,例如:
struct MainView: View {
    var didLogout: () -> ()
    
    // ... other code

  func logout () {
    // ... make logout activity here and on completion perform

    // DispatchQueue.main.async {  << if logout callback in different queue
       didLogout()
    // }
  }
}

现在我们可以将它用作:
func showMainView() {
    let host = UIHostingController(rootView: MainView() { [weak self] in
       self?.navigationController?.popViewController(animated: true)  // << here !!
    })

    self.navigationController?.navigationBar.isHidden = true
    self.navigationController?.pushViewController(host, animated: true)
}

嗨Asperi,谢谢你的回答。我尝试了这个实现,从某种意义上说,它部分地起作用,当回调被触发时,它会弹出到LoginViewController。但是当用户已经登录时,rootViewController将是MainView,因此弹出到LoginViewController的回调不再起作用。你知道另一种在SwiftUI中直接设置根视图的实现方式吗?这样可以返回到UIKit的LoginViewController吗?提前感谢! - undefined

1

这对我非常有效,希望能对你有所帮助!

let storyboard = UIStoryboard(name: "Main", bundle: nil)

let rootViewController = storyboard.instantiateViewController(withIdentifier: "YourIdentifier")

           if let window = UIApplication.shared.windows.first {
               window.rootViewController = rootViewController
               window.endEditing(true)
               window.makeKeyAndVisible()
           }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接