【问题标题】:MVVM UITableViewCell return nilMVVM UITableViewCell 返回零
【发布时间】:2017-02-20 14:30:40
【问题描述】:

我正在尝试在 UITableViewController 上进行 MVVM 集成,但我不断收到:

fatal error: unexpectedly found nil while unwrapping an Optional valuesuper.init(style: style, reuseIdentifier: reuseIdentifier)

怎么会?我想这与它有关:

cell.menuItemViewModel = SideMenuViewModel(menuItem: item)

因为如果我删除此行没有错误?

在 sideMenuController 中设置数据源

func setupDatasource() {

    let sections = [
        SectionModel(model: "menu", items: menuItems)
    ]

    dataSource.configureCell = { (ds, tv, ip, item) in
        let cell: MenuCell = tv.dequeueReusableCell(withIdentifier: self.reuseIdentifier, for: ip) as! MenuCell
        cell.menuItemViewModel = SideMenuViewModel(menuItem: item)


        return cell
    }


    Observable.just(sections)
        .bindTo(tableView.rx.items(dataSource: dataSource))
        .addDisposableTo(disposeBag)
}

MenuItem 模型

struct MenuItem {

    var title: String
    var image: Asset
    var imageSelected: Asset
    var controller: UINavigationController

    init(title: String, image: Asset, imageSelected: Asset, controller: UINavigationController) {
        self.title = title
        self.image = image
        self.imageSelected = imageSelected
        self.controller = controller
    }


}

视图模型

struct SideMenuViewModel {

    let title: String
    let image: UIImage
    let imageSelected: UIImage


    init(menuItem: MenuItem) {
        self.title = menuItem.title
        self.image = UIImage(asset: menuItem.image)
        self.imageSelected = UIImage(asset: menuItem.imageSelected)
    }

}

菜单单元

class MenuCell: UITableViewCell {

    var titleLabel: UILabel!
    var iconImageView: UIImageView!

    var menuItemViewModel: SideMenuViewModel! {
        didSet {
            //Set title
            self.titleLabel.text = menuItemViewModel.title

            //Set image
            self.iconImageView.image = menuItemViewModel.image

        }
    }


    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)


        setupUI()
        setupConstraints()

    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    func setupUI() {

        //Add titleLabel
        self.titleLabel = UILabel()
        self.addSubview(self.titleLabel)

        //Add iconImageView
        self.iconImageView = UIImageView()
        self.addSubview(self.iconImageView)

        //Customize titleLabel
        self.titleLabel.font = FontFamily.Avenir.Regular.font(size: 26)
        self.titleLabel.textColor = UIColor.white.withAlphaComponent(0.6)

        //Customize iconImageView
        self.iconImageView.contentMode = .scaleAspectFit

        //Customize cell
        self.selectionStyle = .none
        self.backgroundColor = UIColor.clear
    }

    func setupConstraints() {

        //titleLabel constraints
        self.titleLabel.snp.makeConstraints({ make in
            make.left.equalTo(self.iconImageView.snp.right).offset(-20)
            make.centerY.equalTo(self)
            make.height.equalTo(50)
            make.width.equalTo(100)
        })

        //iconImageView constraints
        self.iconImageView.snp.makeConstraints({ make in
            make.left.equalTo(80)
            make.centerY.equalTo(self)
            make.height.equalTo(50)
            make.width.equalTo(50)
            make.right.equalTo(self.titleLabel.snp.left).offset(20)
        })

    }


}

【问题讨论】:

  • 首先:调试并找出nil是什么。如果它像您所说的那样在override init(style:, reuseIdentifier:) 中,它必须是reuseIdentifier,因为它是唯一的可选afaics。但是你没有打开它,这很奇怪。这条线在我看来更可疑:let cell: MenuCell = tv.dequeueReusableCell(withIdentifier: self.reuseIdentifier, for: ip) as! MenuCell
  • @shallowThought 好像menuItemViewModel 为零。
  • 请用您的发现更新您的问题。确切的错误出现在哪里以及您已经发现了什么。也许打印调试结果来向我们展示 menuItemViewModel 的确切位置是 nil 并解释为什么你认为此时它不应该是 nil

标签: ios swift mvvm rx-swift


【解决方案1】:

你注册了小区吗?

tableView.register(MenuCell, forCellReuseIdentifier: self.reuseIdentifier)

如果使用 Storyboard 将类添加到单元格中,则无需注册,也不应注册。

此外,当您输入错误的reuseIdentifier 时,您的错误可能会发生。

【讨论】:

  • 是的忘了说我注册了tableView.register(MenuCell.self, forCellReuseIdentifier: self.reuseIdentifier)in viewDidLoad
  • @PeterPik 我认为这可能是您的重用标识符,请确保您的 self.reuseIdentifier 100% 返回与您注册单元格时完全相同的字符串。我更新了我的答案
  • 为什么registercellAtIndexPath都访问fileprivate let reuseIdentifier = "MenuTableCell"时要改变
  • @PeterPik 你也没有在你的问题中包含这个,对我来说很难知道。但是,看看你得到的错误,这就是我怀疑这可能是问题的原因:stackoverflow.com/questions/24643522/… 无论如何,你应该确保它在你的注册和出列方法中都被正确触发。否则,您将返回一个 nil 单元格。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-23
  • 2016-11-24
  • 2021-10-24
  • 2017-11-19
  • 2015-01-23
  • 2016-11-24
相关资源
最近更新 更多