簡體   English   中英

確保viewDidLoad之后屬性觀察者didSet操作用戶界面

[英]Ensure that property observer didSet manipulates User Interface after viewDidLoad

我正在使用MVVM,Coordinators和RxSwift 開發開源教程 我正在協調器中構造所有視圖控制器和模型。 控制器對viewmodel有很強的引用,並且在設置viewmodel時,我想執行一些與UI相關的操作(使用屬性觀察器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)
}

我擔心的是,即使調用manipulateUI在viewDidLoad中目前正在對我來說,如果我忘記從我的協調員讓我覺得我是用一個脆弱的架構設置視圖模型的應用程序會崩潰。 我真的很喜歡從didSet更新用戶界面,但是它在viewDidLoad之前被調用。

我知道這是一個簡單的問題,但是從體系結構的角度來看,它似乎很脆弱。 任何建議,改進和評論都非常感謝。

我不會說這樣的情況可以定義您是否正在處理脆弱的體系結構,因為視圖控制器具有自己的生命周期,這與其他對象的生命周期有很大不同。 無論如何,您可以使用不同的方法輕松地避免崩潰。 例如 :

方法1:

在您的manipulateUI函數的最開始放置一個保護語句,以便該函數在加載視圖和設置模型之前都不會操縱UI。 然后在viewDidLoad方法和設置viewModel時調用此函數:

func manipulateUI(){

    guard let viewModel = self.viewModel , isViewLoaded else {
        return
    }

    //continue manipulation here
} 

方法二:

由於您不確定是否在設置模型時是否加載了視圖並且不知道視圖是否已初始化,因此可以在manipulateUI函數中將視圖作為可選屬性進行訪問:

func manipulateUI(){

    self.someLabel?.text = self.viewModel.someText    

    //continue manipulation here
} 

方法3:

由於您使用的是RxSwift,因此您始終可以為視圖控制器的isViewLoaded屬性注冊一個觀察者,並在確定視圖已加載后設置數據源

發生崩潰是因為此時

rootVC.viewModel = MessageViewModel(withMessage: messages)

視圖控制器未初始化。

它無法按您想要的方式工作,您必須viewDidLoad內部調用handlerUI()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM