确保属性观察者didSet在viewDidLoad

时间:2017-04-21 14:01:09

标签: ios swift mvvm rx-swift

我正在使用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之前被调用。

我知道这是一个简单的问题,但从架构的角度来看,这似乎很脆弱。任何建议,改进和评论都会受到很多赞赏。

2 个答案:

答案 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() >