如何在SwiftUI ViewModel文件中执行Storyboard上的Segue



我目前正在向storyboard中注入一些SwiftUI view+viewModel文件。这样做的理由是,在将来将应用重写为SwiftUI时,我们已经完成了一些工作。在任何情况下,我最终创建了一个托管控制器,它将我的SwitfUI视图文件注入到storyboard中:

class LoginViewHostingController: UIHostingController<LoginView> {
required init?(coder: NSCoder) {
super.init(coder: coder,rootView: LoginView())
}

override func viewDidLoad() {
super.viewDidLoad()
}
}

问题是SwiftUI视图文件使用ViewModel文件(ObservableObject的实例)来执行它的很多逻辑(主要用于状态)。

struct LoginView: View  {

@ObservedObject var loginVM = LoginViewModel()

var body: some View {

…然后视图将使用loginVM这样的:

if (!loginVM.showPasswordView) {
HStack {
Button(action: loginVM.checkEmailForSSOAuthentication) {
Text("Next")
.font(.system(.headline, design: .rounded))
.foregroundColor(Color.white)
.padding(.vertical, 18)
.frame(width: 350)
.background(Color("DigideckPrimary"))
.cornerRadius(6)
}
}
.padding(.top, 10)
}

我要做的,只是确认我能做到,是在storyboard上执行segue这个SwiftUI视图被注入到Next按钮的动作中(loginVM.checkEmailForSSOAuthentication)),我不确定这是否可能。

我尝试在我的loginVM文件:

func checkEmailForSSOAuthentication() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let storyBoardLoginVc = storyboard.instantiateViewController(withIdentifier: "myLoginController")
// instead of sending to self send to main storyboard if i can!
storyBoardLoginVc.performSegue(withIdentifier: "test1", sender: self)
return;

但是在执行此代码时收到以下错误:

2023-01-18 09:47:00.872611-0600 Digideck[35908:12697138] [Assert] UINavigationBar decoded as unlocked for UINavigationController, or navigationBar delegate set up incorrectly. Inconsistent configuration may cause problems. navigationController=<UINavigationController: 0x130879c00>, navigationBar=<UINavigationBar: 0x127e1ce70; frame = (0 0; 0 50); opaque = NO; autoresize = W; tintColor = UIExtendedSRGBColorSpace 0.0784314 0.392157 0.709804 1; gestureRecognizers = <NSArray: 0x6000010ab090>; layer = <CALayer: 0x600001ec0ea0>> delegate=0x130879c00
2023-01-18 09:47:00.873019-0600 Digideck[35908:12697138] [Presentation] Attempt to present <UINavigationController: 0x130879c00> on <Digideck.LoginViewHostingController: 0x10f00b600> (from <Digideck.LoginViewHostingController: 0x10f00b600>) whose view is not in the window hierarchy.

这让我相信我实例化了一个不同的故事板,而不是引用视图中已经存在的故事板。如果有人知道这是可能的,请让我知道!

我们在SwiftUI中不使用视图模型对象,所以认为你将能够在UIKit和SwiftUI中使用它们是不正确的策略。在SwiftUI中,View结构已经是视图模型了,像@State这样的属性包装器给了它们引用类型语义,也就是一个视图模型对象。这一行也是错误的:

@ObservedObject var loginVM = LoginViewModel()

@ObservedObject没有对象的所有权,所以它是init和deinit与视图结构值类型(每次状态更改),所以本质上你已经创建了一个内存泄漏。你需要像这样使用它:

@ObservedObject var model: Model

Model在其他地方被初始化,比如单例,或者在应用程序委托中,也就是说,它有一个不是临时结构值类型的所有者。

我认为最好设计你的SwiftUI视图使用@Binding var代替(如果你需要写访问,否则只是let)。

最新更新