Road to MVC: the case of Settings Table View ControllerRewrite code from Objective-C to conform with Swift power tools and concise styleMVC controller codeFolder model controller viewCommunication between View and Controller in MVC implementationPHP MVC simple controller designModel view controllerASP MVC Controller Unit TestiOS MQTT client app base view controllerSettings the height of rows for multiple screens within a TableViewControllerSwift Attempt To Reduce Massive View ControllerFat-free MVC Controller

How does a computer interpret real numbers?

How does the math work for Perception checks?

How much character growth crosses the line into breaking the character

What is going on with 'gets(stdin)' on the site coderbyte?

What should you do when eye contact makes your subordinate uncomfortable?

How can "mimic phobia" be cured or prevented?

Limits and Infinite Integration by Parts

Do the primes contain an infinite almost arithmetic progression?

Why does AES have exactly 10 rounds for a 128-bit key, 12 for 192 bits and 14 for a 256-bit key size?

How should I respond when I lied about my education and the company finds out through background check?

Open a doc from terminal, but not by its name

Fear of getting stuck on one programming language / technology that is not used in my country

Does the Linux kernel need a file system to run?

Temporarily disable WLAN internet access for children, but allow it for adults

Has any country ever had 2 former presidents in jail simultaneously?

Can I say "fingers" when referring to toes?

What happens if you are holding an Iron Flask with a demon inside and walk into an Antimagic Field?

Is aluminum electrical wire used on aircraft?

Using substitution ciphers to generate new alphabets in a novel

Why would a new[] expression ever invoke a destructor?

Redundant comparison & "if" before assignment

Keeping a ball lost forever

Mimic lecturing on blackboard, facing audience

Why does a simple loop result in ASYNC_NETWORK_IO waits?



Road to MVC: the case of Settings Table View Controller


Rewrite code from Objective-C to conform with Swift power tools and concise styleMVC controller codeFolder model controller viewCommunication between View and Controller in MVC implementationPHP MVC simple controller designModel view controllerASP MVC Controller Unit TestiOS MQTT client app base view controllerSettings the height of rows for multiple screens within a TableViewControllerSwift Attempt To Reduce Massive View ControllerFat-free MVC Controller













5












$begingroup$


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:



enter image description here



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 variable
private var observerContext = 0

class 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?










share|improve this question











$endgroup$




bumped to the homepage by Community 16 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.










  • 1




    $begingroup$
    About passing a model to the view; usually it's recommended to pass a ViewModel instead of a DataModel. Essentially, they're simple models that only have data needed by the view. You would strip fields that are not needed, and you can compose multiple data models into one view model, specific to your view. At least, that's how I understand it.
    $endgroup$
    – Ivo Coumans
    Sep 29 '14 at 13:37











  • $begingroup$
    Thanks for your comment. However, I can hardly translate it to real code. The truth is that it's easy to find theoretical answers about MVC and MVVM but really hard to find practical answers. Since Swift has been launched, I've only been able to find two MVC/MVVM concrete explanations for it (the Rob Mayoff's answer to a previous question and a Natasha The Robot blog post). Would you give a try for this question?
    $endgroup$
    – user53113
    Sep 29 '14 at 14:05










  • $begingroup$
    Unfortunately I'm not familiar with Swift at all, which is why I only left a comment, hoping to give you a little advice.
    $endgroup$
    – Ivo Coumans
    Sep 29 '14 at 14:19










  • $begingroup$
    @IvoCoumans viewmodel is equivalent of controller in the pattern of MVVM, it's definitely different from model, so I don't agree with your point of passing some view model to controller.
    $endgroup$
    – zinking
    Oct 6 '14 at 1:58















5












$begingroup$


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:



enter image description here



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 variable
private var observerContext = 0

class 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?










share|improve this question











$endgroup$




bumped to the homepage by Community 16 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.










  • 1




    $begingroup$
    About passing a model to the view; usually it's recommended to pass a ViewModel instead of a DataModel. Essentially, they're simple models that only have data needed by the view. You would strip fields that are not needed, and you can compose multiple data models into one view model, specific to your view. At least, that's how I understand it.
    $endgroup$
    – Ivo Coumans
    Sep 29 '14 at 13:37











  • $begingroup$
    Thanks for your comment. However, I can hardly translate it to real code. The truth is that it's easy to find theoretical answers about MVC and MVVM but really hard to find practical answers. Since Swift has been launched, I've only been able to find two MVC/MVVM concrete explanations for it (the Rob Mayoff's answer to a previous question and a Natasha The Robot blog post). Would you give a try for this question?
    $endgroup$
    – user53113
    Sep 29 '14 at 14:05










  • $begingroup$
    Unfortunately I'm not familiar with Swift at all, which is why I only left a comment, hoping to give you a little advice.
    $endgroup$
    – Ivo Coumans
    Sep 29 '14 at 14:19










  • $begingroup$
    @IvoCoumans viewmodel is equivalent of controller in the pattern of MVVM, it's definitely different from model, so I don't agree with your point of passing some view model to controller.
    $endgroup$
    – zinking
    Oct 6 '14 at 1:58













5












5








5


1



$begingroup$


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:



enter image description here



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 variable
private var observerContext = 0

class 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?










share|improve this question











$endgroup$




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:



enter image description here



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 variable
private var observerContext = 0

class 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?







swift mvc ios cocoa






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 21 at 4:07









200_success

130k17155419




130k17155419










asked Sep 21 '14 at 15:24







user53113












bumped to the homepage by Community 16 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.







bumped to the homepage by Community 16 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.









  • 1




    $begingroup$
    About passing a model to the view; usually it's recommended to pass a ViewModel instead of a DataModel. Essentially, they're simple models that only have data needed by the view. You would strip fields that are not needed, and you can compose multiple data models into one view model, specific to your view. At least, that's how I understand it.
    $endgroup$
    – Ivo Coumans
    Sep 29 '14 at 13:37











  • $begingroup$
    Thanks for your comment. However, I can hardly translate it to real code. The truth is that it's easy to find theoretical answers about MVC and MVVM but really hard to find practical answers. Since Swift has been launched, I've only been able to find two MVC/MVVM concrete explanations for it (the Rob Mayoff's answer to a previous question and a Natasha The Robot blog post). Would you give a try for this question?
    $endgroup$
    – user53113
    Sep 29 '14 at 14:05










  • $begingroup$
    Unfortunately I'm not familiar with Swift at all, which is why I only left a comment, hoping to give you a little advice.
    $endgroup$
    – Ivo Coumans
    Sep 29 '14 at 14:19










  • $begingroup$
    @IvoCoumans viewmodel is equivalent of controller in the pattern of MVVM, it's definitely different from model, so I don't agree with your point of passing some view model to controller.
    $endgroup$
    – zinking
    Oct 6 '14 at 1:58












  • 1




    $begingroup$
    About passing a model to the view; usually it's recommended to pass a ViewModel instead of a DataModel. Essentially, they're simple models that only have data needed by the view. You would strip fields that are not needed, and you can compose multiple data models into one view model, specific to your view. At least, that's how I understand it.
    $endgroup$
    – Ivo Coumans
    Sep 29 '14 at 13:37











  • $begingroup$
    Thanks for your comment. However, I can hardly translate it to real code. The truth is that it's easy to find theoretical answers about MVC and MVVM but really hard to find practical answers. Since Swift has been launched, I've only been able to find two MVC/MVVM concrete explanations for it (the Rob Mayoff's answer to a previous question and a Natasha The Robot blog post). Would you give a try for this question?
    $endgroup$
    – user53113
    Sep 29 '14 at 14:05










  • $begingroup$
    Unfortunately I'm not familiar with Swift at all, which is why I only left a comment, hoping to give you a little advice.
    $endgroup$
    – Ivo Coumans
    Sep 29 '14 at 14:19










  • $begingroup$
    @IvoCoumans viewmodel is equivalent of controller in the pattern of MVVM, it's definitely different from model, so I don't agree with your point of passing some view model to controller.
    $endgroup$
    – zinking
    Oct 6 '14 at 1:58







1




1




$begingroup$
About passing a model to the view; usually it's recommended to pass a ViewModel instead of a DataModel. Essentially, they're simple models that only have data needed by the view. You would strip fields that are not needed, and you can compose multiple data models into one view model, specific to your view. At least, that's how I understand it.
$endgroup$
– Ivo Coumans
Sep 29 '14 at 13:37





$begingroup$
About passing a model to the view; usually it's recommended to pass a ViewModel instead of a DataModel. Essentially, they're simple models that only have data needed by the view. You would strip fields that are not needed, and you can compose multiple data models into one view model, specific to your view. At least, that's how I understand it.
$endgroup$
– Ivo Coumans
Sep 29 '14 at 13:37













$begingroup$
Thanks for your comment. However, I can hardly translate it to real code. The truth is that it's easy to find theoretical answers about MVC and MVVM but really hard to find practical answers. Since Swift has been launched, I've only been able to find two MVC/MVVM concrete explanations for it (the Rob Mayoff's answer to a previous question and a Natasha The Robot blog post). Would you give a try for this question?
$endgroup$
– user53113
Sep 29 '14 at 14:05




$begingroup$
Thanks for your comment. However, I can hardly translate it to real code. The truth is that it's easy to find theoretical answers about MVC and MVVM but really hard to find practical answers. Since Swift has been launched, I've only been able to find two MVC/MVVM concrete explanations for it (the Rob Mayoff's answer to a previous question and a Natasha The Robot blog post). Would you give a try for this question?
$endgroup$
– user53113
Sep 29 '14 at 14:05












$begingroup$
Unfortunately I'm not familiar with Swift at all, which is why I only left a comment, hoping to give you a little advice.
$endgroup$
– Ivo Coumans
Sep 29 '14 at 14:19




$begingroup$
Unfortunately I'm not familiar with Swift at all, which is why I only left a comment, hoping to give you a little advice.
$endgroup$
– Ivo Coumans
Sep 29 '14 at 14:19












$begingroup$
@IvoCoumans viewmodel is equivalent of controller in the pattern of MVVM, it's definitely different from model, so I don't agree with your point of passing some view model to controller.
$endgroup$
– zinking
Oct 6 '14 at 1:58




$begingroup$
@IvoCoumans viewmodel is equivalent of controller in the pattern of MVVM, it's definitely different from model, so I don't agree with your point of passing some view model to controller.
$endgroup$
– zinking
Oct 6 '14 at 1:58










1 Answer
1






active

oldest

votes


















0












$begingroup$

Not familiar with Swift at all. but still want to add some comments.



the primary goal of design pattern of "MVC" is to separate the aspects involved, so that extension and modification can be done easily. so yes MVC definitely involves "MODEL" "VIEW" "CONTROLLER". but as you might know it has several mutations: MVVM,MTV(in the case of Django framework). The key is along the directions of separation you made something like that, but I myself don't get bureaucratic about that, as long as I think the refactoring made the whole process much clear, I am okay with my "MVC".



In the case of your refactoring, I am seeing a bit chunk of logic separated into controllers, views, models. which is good enough for me in terms of "MVC".






share|improve this answer









$endgroup$












  • $begingroup$
    I generally go follow this wisdom, <jiggliemon> MVD, Model View Don't ask
    $endgroup$
    – megawac
    Oct 6 '14 at 4:25










Your Answer





StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f63484%2froad-to-mvc-the-case-of-settings-table-view-controller%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown
























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0












$begingroup$

Not familiar with Swift at all. but still want to add some comments.



the primary goal of design pattern of "MVC" is to separate the aspects involved, so that extension and modification can be done easily. so yes MVC definitely involves "MODEL" "VIEW" "CONTROLLER". but as you might know it has several mutations: MVVM,MTV(in the case of Django framework). The key is along the directions of separation you made something like that, but I myself don't get bureaucratic about that, as long as I think the refactoring made the whole process much clear, I am okay with my "MVC".



In the case of your refactoring, I am seeing a bit chunk of logic separated into controllers, views, models. which is good enough for me in terms of "MVC".






share|improve this answer









$endgroup$












  • $begingroup$
    I generally go follow this wisdom, <jiggliemon> MVD, Model View Don't ask
    $endgroup$
    – megawac
    Oct 6 '14 at 4:25















0












$begingroup$

Not familiar with Swift at all. but still want to add some comments.



the primary goal of design pattern of "MVC" is to separate the aspects involved, so that extension and modification can be done easily. so yes MVC definitely involves "MODEL" "VIEW" "CONTROLLER". but as you might know it has several mutations: MVVM,MTV(in the case of Django framework). The key is along the directions of separation you made something like that, but I myself don't get bureaucratic about that, as long as I think the refactoring made the whole process much clear, I am okay with my "MVC".



In the case of your refactoring, I am seeing a bit chunk of logic separated into controllers, views, models. which is good enough for me in terms of "MVC".






share|improve this answer









$endgroup$












  • $begingroup$
    I generally go follow this wisdom, <jiggliemon> MVD, Model View Don't ask
    $endgroup$
    – megawac
    Oct 6 '14 at 4:25













0












0








0





$begingroup$

Not familiar with Swift at all. but still want to add some comments.



the primary goal of design pattern of "MVC" is to separate the aspects involved, so that extension and modification can be done easily. so yes MVC definitely involves "MODEL" "VIEW" "CONTROLLER". but as you might know it has several mutations: MVVM,MTV(in the case of Django framework). The key is along the directions of separation you made something like that, but I myself don't get bureaucratic about that, as long as I think the refactoring made the whole process much clear, I am okay with my "MVC".



In the case of your refactoring, I am seeing a bit chunk of logic separated into controllers, views, models. which is good enough for me in terms of "MVC".






share|improve this answer









$endgroup$



Not familiar with Swift at all. but still want to add some comments.



the primary goal of design pattern of "MVC" is to separate the aspects involved, so that extension and modification can be done easily. so yes MVC definitely involves "MODEL" "VIEW" "CONTROLLER". but as you might know it has several mutations: MVVM,MTV(in the case of Django framework). The key is along the directions of separation you made something like that, but I myself don't get bureaucratic about that, as long as I think the refactoring made the whole process much clear, I am okay with my "MVC".



In the case of your refactoring, I am seeing a bit chunk of logic separated into controllers, views, models. which is good enough for me in terms of "MVC".







share|improve this answer












share|improve this answer



share|improve this answer










answered Oct 6 '14 at 2:04









zinkingzinking

1176




1176











  • $begingroup$
    I generally go follow this wisdom, <jiggliemon> MVD, Model View Don't ask
    $endgroup$
    – megawac
    Oct 6 '14 at 4:25
















  • $begingroup$
    I generally go follow this wisdom, <jiggliemon> MVD, Model View Don't ask
    $endgroup$
    – megawac
    Oct 6 '14 at 4:25















$begingroup$
I generally go follow this wisdom, <jiggliemon> MVD, Model View Don't ask
$endgroup$
– megawac
Oct 6 '14 at 4:25




$begingroup$
I generally go follow this wisdom, <jiggliemon> MVD, Model View Don't ask
$endgroup$
– megawac
Oct 6 '14 at 4:25

















draft saved

draft discarded
















































Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f63484%2froad-to-mvc-the-case-of-settings-table-view-controller%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

名間水力發電廠 目录 沿革 設施 鄰近設施 註釋 外部連結 导航菜单23°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.7113923°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.71139計畫概要原始内容臺灣第一座BOT 模式開發的水力發電廠-名間水力電廠名間水力發電廠 水利署首件BOT案原始内容《小檔案》名間電廠 首座BOT水力發電廠原始内容名間電廠BOT - 經濟部水利署中區水資源局

Prove that NP is closed under karp reduction?Space(n) not closed under Karp reductions - what about NTime(n)?Class P is closed under rotation?Prove or disprove that $NL$ is closed under polynomial many-one reductions$mathbfNC_2$ is closed under log-space reductionOn Karp reductionwhen can I know if a class (complexity) is closed under reduction (cook/karp)Check if class $PSPACE$ is closed under polyonomially space reductionIs NPSPACE also closed under polynomial-time reduction and under log-space reduction?Prove PSPACE is closed under complement?Prove PSPACE is closed under union?

Is my guitar’s action too high? Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)Strings too stiff on a recently purchased acoustic guitar | Cort AD880CEIs the action of my guitar really high?Μy little finger is too weak to play guitarWith guitar, how long should I give my fingers to strengthen / callous?When playing a fret the guitar sounds mutedPlaying (Barre) chords up the guitar neckI think my guitar strings are wound too tight and I can't play barre chordsF barre chord on an SG guitarHow to find to the right strings of a barre chord by feel?High action on higher fret on my steel acoustic guitar