0

I'm trying to make an MVVM integration on a UITableViewController, however I keep getting:

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

How come? I guess it has something to do with:

cell.menuItemViewModel = SideMenuViewModel(menuItem: item)

since there is no error if I remove this line?

setting datasource in 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 model

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
    }


}

ViewModel

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)
    }

}

MenuCell

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)
        })

    }


}
Peter Pik
  • 10,263
  • 17
  • 73
  • 131
  • First: debug and find out what's `nil`. If it's in `override init(style:, reuseIdentifier:)` like you are saying, it must be `reuseIdentifier`, as it is the only Optional afaics. But you are not unwrapping it, which is strange. This line looks more suspicious to me: `let cell: MenuCell = tv.dequeueReusableCell(withIdentifier: self.reuseIdentifier, for: ip) as! MenuCell` – shallowThought Feb 20 '17 at 14:46
  • @shallowThought it seems like `menuItemViewModel` is nil. – Peter Pik Feb 20 '17 at 14:51
  • Please update your question with your findings. Where exactly does what exact error show up and what did you find out already. Maybe print debug results to show us for instance where exactly `menuItemViewModel` is `nil` and explain why you think it should not be `nil` at this point. – shallowThought Feb 20 '17 at 15:13

1 Answers1

0

Did you register the cell ?

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

If using Storyboard to add the class to the cell, then no need to register it and you should not register.

Also, your error can occur when you have the wrong reuseIdentifier.

  • yes forgot to mention I registered `tableView.register(MenuCell.self, forCellReuseIdentifier: self.reuseIdentifier)`in `viewDidLoad` – Peter Pik Feb 20 '17 at 14:35
  • @PeterPik I think it might be your reuseidentifier then, make sure 100% that your self.reuseIdentifier returns the EXACT same string as you register the cell with. I updated my answer –  Feb 20 '17 at 14:37
  • why should they change when `register` and `cellAtIndexPath` both access `fileprivate let reuseIdentifier = "MenuTableCell"` – Peter Pik Feb 20 '17 at 14:39
  • @PeterPik You have not included that in your question neither, hard to know for me. However, looking at the error you are getting thats why I suspected that could be the issue: http://stackoverflow.com/questions/24643522/fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-values Anyhow, you should make sure that it gets fired off correctly both in your register and dequeue methods. Otherwise you will return a nil cell. –  Feb 20 '17 at 14:46