Now that I know that MVC can help do better code, I want to make my SettingsTableViewController class conform to it.SettingsTableViewController is a subclass of UITableViewController. It is linked to a storyboard scene that contains a UITableView with two cells (grouped tableView style, prototype cells). The first cell has a right detail style (textLabel and detailTextLabel), the second cell has a custom style and displays a UIPickerView inside of its contentView.When it appears on screen, SettingsTableViewController displays only the first cell. When I click on this cell, the second cell containing a UIPickerView appears. If I click again on the first cell, the second cell disappears.The detailtextLabel of the first row displays an integer saved in NSUserDefaults. The pickerView of the second cell is linked to an array of integers. When I select a row in the pickerView, it saves the row's related integer in NSUserDefaults and updates the detailtextLabel of the first cell.The image below may help understand the way it works:Before knowing the concept of MVC, I was able to write the following code to make the previous explanation work:class SettingsTableViewController: UITableViewController, UIPickerViewDelegate, UIPickerViewDataSource {    let itemsArray = [5, 10, 15]    var pickerIndexPath: NSIndexPath? //acts like a Bool and allows to hide or show cell with identifier pickerCell    var numberOfItems: Int {        get {            return NSUserDefaults.standardUserDefaults().integerForKey(NumberOfItems)        }        set {            NSUserDefaults.standardUserDefaults().setInteger(newValue, forKey: NumberOfItems)            NSUserDefaults.standardUserDefaults().synchronize()        }    }    override func viewDidLoad() {        super.viewDidLoad()        title = Settings        //Init numberOfItems        if numberOfItems == 0 {            numberOfItems = 5        }        //Autoset cells height (iOS8)        tableView.rowHeight = UITableViewAutomaticDimension        tableView.estimatedRowHeight = 44    }    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {        return 1    }    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {        //If pickerIndexPath is nil, show only one cell        return pickerIndexPath == nil ? 1 : 2    }    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {        var cell: UITableViewCell!        if indexPath.row == 0 {            cell = tableView.dequeueReusableCellWithIdentifier(RightDetailCell, forIndexPath: indexPath) as UITableViewCell            cell.textLabel?.text = Items            cell.detailTextLabel?.text = \(numberOfItems)        } else {            cell = tableView.dequeueReusableCellWithIdentifier(PickerCell, forIndexPath: indexPath) as UITableViewCell            cell.selectionStyle = .None            //Set pickerView inside cell            let picker = cell.viewWithTag(1) as UIPickerView            picker.delegate = self            picker.dataSource = self            //Set the middle row in picker according to numberOfItems            if let index = find(itemsArray, numberOfItems) {                picker.selectRow(index, inComponent: 0, animated: false)            }        }        return cell    }    override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {        switch indexPath {        case NSIndexPath(forRow: 1, inSection: 0):            return nil        default:            return indexPath        }    }    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {        tableView.deselectRowAtIndexPath(indexPath, animated: true)        if indexPath == NSIndexPath(forRow: 0, inSection: 0) {            //Show or hide pickerCell            if pickerIndexPath == nil {                tableView.beginUpdates()                pickerIndexPath = NSIndexPath(forRow: 1, inSection: 0)                tableView.insertRowsAtIndexPaths([pickerIndexPath!], withRowAnimation: .Fade)                tableView.endUpdates()            } else {                tableView.beginUpdates()                tableView.deleteRowsAtIndexPaths([pickerIndexPath!], withRowAnimation: .Fade)                pickerIndexPath = nil                tableView.endUpdates()            }        }    }    //MARK: UIPickerViewDataSource    func numberOfComponentsInPickerView(_: UIPickerView) -> Int {        return 1    }    func pickerView(_: UIPickerView, numberOfRowsInComponent component: Int) -> Int {        return itemsArray.count    }    //MARK: UIPickerViewDelegate    func pickerView(_: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {        return \(itemsArray[row]) items    }    func pickerView(_: UIPickerView, didSelectRow row: Int, inComponent component: Int) {        if pickerIndexPath != nil {            //save new value in NSUserDefaults            numberOfItems = itemsArray[row]            //update first cell            let index = NSIndexPath(forRow: pickerIndexPath!.row - 1, inSection: 0)            tableView.reloadRowsAtIndexPaths([index], withRowAnimation: .Fade)        }    }    override func didReceiveMemoryWarning() {        super.didReceiveMemoryWarning()    }}Then, in order to conform to MVC design pattern, I replaced the previous code with the following:SettingsTableViewController:class SettingsTableViewController: UITableViewController {    let dataSource = DataSource()    override func viewDidLoad() {        super.viewDidLoad()        title = Settings        //Autoset cells height (iOS8)        tableView.rowHeight = UITableViewAutomaticDimension        tableView.estimatedRowHeight = 44    }    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {        return 1    }    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {        //If pickerIndexPath is nil, show only one cell        return dataSource.pickerIndexPath == nil ? 1 : 2    }    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {        if indexPath.row == 0 {            let cell = tableView.dequeueReusableCellWithIdentifier(LabelCell, forIndexPath: indexPath) as LabelCell            cell.dataSource = dataSource            return cell        } else {            let cell = tableView.dequeueReusableCellWithIdentifier(PickerCell, forIndexPath: indexPath) as PickerCell            cell.dataSource = dataSource            return cell        }    }    override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {        switch indexPath {        case NSIndexPath(forRow: 1, inSection: 0):            return nil        default:            return indexPath        }    }    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {        tableView.deselectRowAtIndexPath(indexPath, animated: true)        if indexPath == NSIndexPath(forRow: 0, inSection: 0) {            //Show or hide pickerCell            tableView.beginUpdates()            if dataSource.pickerIndexPath == nil {                dataSource.pickerIndexPath = NSIndexPath(forRow: indexPath.row + 1, inSection: 0)                tableView.insertRowsAtIndexPaths([dataSource.pickerIndexPath!], withRowAnimation: .Fade)            } else {                tableView.deleteRowsAtIndexPaths([dataSource.pickerIndexPath!], withRowAnimation: .Fade)                dataSource.pickerIndexPath = nil            }            tableView.endUpdates()        }    }    override func didReceiveMemoryWarning() {        super.didReceiveMemoryWarning()    }}LabelCell://Global context variableprivate var observerContext = 0class LabelCell: UITableViewCell {    var dataSource: DataSource? {        willSet {            disconnectFromModel()        }        didSet {            connectToModel()            update()        }    }    private func disconnectFromModel() {        dataSource?.removeObserver(self, forKeyPath: numberOfItems, context: &observerContext)    }    private func connectToModel() {        dataSource?.addObserver(self, forKeyPath: numberOfItems, options: NSKeyValueObservingOptions(), context: &observerContext)    }    override func observeValueForKeyPath(keyPath: String!, ofObject object: AnyObject!, change: [NSObject : AnyObject]!, context: UnsafeMutablePointer<Void>) {        if context == &observerContext {            update()        } else {            super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)        }    }    private func update() {        if let model = dataSource {            textLabel?.text = Items            detailTextLabel?.text = \(model.numberOfItems)        }    }    deinit {        disconnectFromModel()    }}PickerCell:class PickerCell: UITableViewCell, UIPickerViewDelegate, UIPickerViewDataSource {    @IBOutlet weak var picker: UIPickerView!    var dataSource: DataSource? {        didSet {            update()        }    }    override func awakeFromNib() {        super.awakeFromNib()        selectionStyle = .None        picker.delegate = self        picker.dataSource = self    }    func update() {        if let dataSource = dataSource {            if let index = find(dataSource.itemsArray, dataSource.inspectionPref) {                picker.selectRow(index, inComponent: 0, animated: false)            }        }    }    //MARK: UIPickerViewDataSource    func numberOfComponentsInPickerView(_: UIPickerView) -> Int {        return 1    }    func pickerView(_: UIPickerView, numberOfRowsInComponent component: Int) -> Int {        return dataSource!.itemsArray.count    }    //MARK: UIPickerViewDelegate    func pickerView(_: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {        return \(dataSource!.itemsArray[row]) items    }    func pickerView(_: UIPickerView, didSelectRow row: Int, inComponent component: Int) {        dataSource!.numberOfItems = dataSource!.itemsArray[row]    }}DataSource:class DataSource: NSObject {    let itemsArray = [5, 10, 15]    var pickerIndexPath: NSIndexPath? //allows to hide or show cell with identifier pickerCell    dynamic var numberOfItems: Int {        get {            return NSUserDefaults.standardUserDefaults().integerForKey(NumberOfItems)        }        set {            NSUserDefaults.standardUserDefaults().setInteger(newValue, forKey: NumberOfItems)            NSUserDefaults.standardUserDefaults().synchronize()        }    }    override init() {        super.init()        //Init numberOfItems at first launch        if numberOfItems == 0 {            numberOfItems = 5        }    }}I have several questions about this new code. As it is my first attempt with MVC, I wonder if it is a real MVC design pattern code. I also ask myself if it is a complete/correct MVC code: is there anything left to do/modify in order to fully conform to MVC? Furthermore, I've read that passing a model to a view (here, a cell) is not recommended. Thus, what would be the way to make a cell interact with the model without passing the model to it?
Road to MVC: the case of Settings Table View Controller
design patterns;mvc;ios;swift