我正在使用MVVM,Coordinators和RxSwift工作open source tutorial。我正在构建协调器中的所有viewcontrollers和模型。 Controller有一个对viewmodel的强引用,当设置viewmodel时,我想执行一些与UI相关的操作(使用属性observer didSet)。我面临的问题是在 viewDidLoad 导致崩溃之前调用 didSet 。
ViewController的简化版本:
class MessageVC: UIViewController {
var viewModel: MessageViewModel! {
didSet {
manipulateUI() // crashes
}
}
override func viewDidLoad() {
super.viewDidLoad()
manipulateUI() // works fine if setup is correct in coordinator
}
协调员剥离版本:
extension AppCoordinator {
convenience init() {
let rootVC = MessageVC() // actual construction from storyboard
let messages = Message.getMessages()
rootVC.viewModel = MessageViewModel(withMessage: messages)
}
我担心的是,即使在viewDidLoad中调用 manipulateUI 当前正在为我工作,如果我忘记从我的协调员设置viewModel让我觉得我正在使用脆弱的建筑。我真的很喜欢从didSet更新用户界面,但它在viewDidLoad之前被调用。
我知道这是一个简单的问题,但从架构的角度来看,这似乎很脆弱。任何建议,改进和评论都会受到很多赞赏。
答案 0 :(得分:1)
我不会说像这样的情况可以定义你是否正在处理脆弱的架构,因为视图控制器有自己的生命周期,它与其他对象的生命周期有很大的不同。无论如何,你可以使用不同的方法轻松避免崩溃。例如:
方法1:
在manipulateUI
函数的最开头放置一个保护语句,这样这个函数就不会操纵UI,直到加载了视图并设置了模型。然后在viewDidLoad
方法上调用此函数,并在设置viewModel时使用:
func manipulateUI(){
guard let viewModel = self.viewModel , isViewLoaded else {
return
}
//continue manipulation here
}
方法2:
由于您不确定在设置模型时是否加载了视图,并且不知道视图是否已初始化,因此您可以在manipulateUI
函数中将视图作为可选属性进行访问:
func manipulateUI(){
self.someLabel?.text = self.viewModel.someText
//continue manipulation here
}
方法3:
由于您使用的是RxSwift,因此您始终可以为视图控制器的isViewLoaded
属性注册观察者,并在确定加载视图后设置数据源
答案 1 :(得分:0)
发生崩溃是因为此时
rootVC.viewModel = MessageViewModel(withMessage: messages)
视图控制器未初始化。
它不会按照您尝试完成的方式工作,必须在 viewDidLoad 中调用操纵UI() >