【问题标题】:app crash when success initialize data MVVM成功初始化数据MVVM时应用程序崩溃
【发布时间】:2020-04-11 08:50:09
【问题描述】:

当我尝试将数据传递到另一个控制器时,我的应用程序崩溃了,但它已成功在我的 viewController 中加载数据。这有点奇怪,因为数据成功显示在我的标签和我的控制器中的 imageView 中,我可以怀疑数据尚未加载。但是如果数据没有被加载,为什么 imageView 会显示我的数据,这里我给你看我的代码。

// This is my schoolListViewModel
class SchoolListViewModel {

    private(set) var schoolListViewModel = [SchoolViewModel]()
    private let services: ProfileServices
    private let schools = UserDefaults.getSelectedSchool()

    var count: Int {
        return schoolListViewModel.count
    }

    var id: String {
        selectedSchoolID()
    }

    var imageUrl: String {
        selectedSchoolImageURL()
    }

    var schoolName: String {
        selectedSchoolName()
    }

    var schoolCity: String {
        selectedSchoolCity()
    }

    init(services: ProfileServices) {
        self.services = services
    }
}

extension SchoolListViewModel {

    func loadData(success: @escaping (() -> Void), failure: @escaping ((String) -> Void)) {
        services.fetchSchoolList { [weak self] result in
            switch result {
            case .success(let schools):
                self?.schoolListViewModel = schools.compactMap({ SchoolViewModel(school: $0)
                })
                success()
            case .failure(let error):
                failure(error.localizedDescription)
            }
        }
    }
}

// this is in my profileViewController
   var schoolListViewModel: SchoolListViewModel!
   private let profileServices = ProfileServices()

// this is my viewModel in my viewDidLoad
   progressHUD.show(in: self.view)
   schoolListViewModel = SchoolListViewModel(services: profileServices)
   schoolListViewModel.loadData(success: {
      self.progressHUD.dismiss(animated: true)
      self.populateSchool()
   }) { [weak self] error in
      self?.showHUDWithError(error)
   }

   schoolSelectionBtn.addTarget(self, action: #selector(handlePickSchool), for: .touchUpInside)

// This is my objc function
   private func showHUDWithError(_ error: String) {
        progressHUD.textLabel.text = "Error"
        progressHUD.detailTextLabel.text = error
        progressHUD.dismiss(afterDelay: 4)
    }

   @objc private func handlePickSchool() {
      let selectSchoolVC = SelectSchoolPopUpVC()
      selectSchoolVC.schoolListViewModel = schoolListViewModel

      present(selectSchoolVC, animated: true, completion: nil)
   }

// this is in my SchoolPopUpVC controller
var schoolListViewModel: SchoolListViewModel!

// this is where the error goes in my schoolPopUpVC tableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return schoolListViewModel.count
    }

当我尝试传递数据时,错误显示在我的 tableView numberOfRowsInSection 中

尝试解开可选值时意外发现 nil

【问题讨论】:

  • 除非你想崩溃,否则不要使用! - 正确解开你的选项并在数据加载完成后通知你的视图刷新 - 这是一个异步网络操作。
  • 但是@Paulw11 我使用加载来等待数据完成,这就是为什么当数据完成但仍然崩溃时它很奇怪。顺便更新一下问题,我在异步网络完成后添加进度加载。
  • 它在哪一行崩溃?显示该代码。
  • @Paulw11 我更新了崩溃出现的问题
  • 将其更改为 return schoolListViewModel?.count ?? 0 - 避免 nil 的强制展开

标签: ios swift uitableview mvvm


【解决方案1】:

您正在为schoolListViewModel 使用隐式展开的可选选项,但在viewDidLoad 执行之前您不会分配值。顾名思义,该方法在视图加载后执行。您在numberOfRowsInSection 中引用schoolListViewModel,它将在视图加载后但在viewDidLoad 执行之前调用,因此您会崩溃。

简单的解决方法是在该方法中有条件地解开schoolListViewModel

return schoolListViewModel?.count ?? 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多