MVC vs MVVC in iOS Development

MVC vs MVVC in iOS Development
Design patterns of a finely-tuned machine

Model-View-Controller (MVC) and Model-View-ViewModel (MVVM) are both design patterns that are commonly used in iOS development to structure the code of an iOS application. Both patterns are used to separate the concerns of an application, such as the data model, the user interface, and the control flow.

MVC

MVC (Model-View-Controller) is a design pattern that separates an application into three main components: the model, the view, and the controller. The model represents the data and the business logic of the application, the view represents the user interface, and the controller manages the flow of data between the model and the view.

For example, consider a simple iOS application that allows a user to view and edit a list of contacts. The model in this application would be a data structure that holds information about each contact, such as their name, phone number, and email address. The view would be the user interface that displays the list of contacts and allows the user to edit them. The controller would handle the logic for adding, editing, and deleting contacts in the data model, and updating the view to reflect these changes.

Model: This is a simple struct that represents a contact with a name, phone number, and email address. It could also include methods that perform business logic, such as validation or formatting of the contact information.

// Model

struct Contact {
    var name: String
    var phone: String
    var email: String
}

View: This is a UIView subclass that represents the user interface for displaying a contact. It has outlets for three labels that will display the contact's name, phone number, and email address. The display method is used to set the text of the labels to the corresponding properties of the contact.

// View

class ContactView: UIView {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var phoneLabel: UILabel!
    @IBOutlet weak var emailLabel: UILabel!

    func display(contact: Contact) {
        nameLabel.text = contact.name
        phoneLabel.text = contact.phone
        emailLabel.text = contact.email
    }
}

Controller: This is a UIViewController subclass that manages the flow of data between the model and the view. It has an outlet for the ContactView and a property for the Contact. When the contact property is set, the controller updates the view by calling the display method on the contactView.

In this example, the controller is responsible for handling user interactions (e.g. button taps) and updating the model and the view accordingly. The model represents the data and business logic of the application, and the view represents the user interface.

// Controller

class ContactViewController: UIViewController {
    @IBOutlet weak var contactView: ContactView!

    var contact: Contact? {
        didSet {
            guard let contact = contact else { return }
            contactView.display(contact: contact)
        }
    }
}

MVVM

MVVM (Model-View-ViewModel) is similar to MVC, but it has some key differences. Like MVC, MVVM separates an application into three main components: the model, the view, and the view-model. The model represents the data and the business logic, the view represents the user interface, and the view-model acts as a bridge between the model and the view, providing data bindings and other mechanisms to keep the view and the model in sync.

For example, consider the same iOS application as above, but using MVVM. The model would be the same data structure that holds information about each contact. The view would be the user interface that displays the list of contacts and allows the user to edit them, but instead of having a separate controller, the view-model would handle the logic for adding, editing, and deleting contacts in the data model, and updating the view to reflect these changes, providing data bindings and other mechanisms to keep the view and the model in sync.

Model: This is a simple struct that represents a contact with a name, phone number, and email address. It could also include methods that perform business logic, such as validation or formatting of the contact information.

// Model

struct Contact {
    var name: String
    var phone: String
    var email: String
}

View: This is a UIView subclass that represents the user interface for displaying a contact. It has outlets for three labels that will display the contact's name, phone number, and email address. It also has a property for a ContactViewModel. When the viewModel property is set, the view updates the text of the labels to the corresponding properties of the viewModel.

// View

class ContactView: UIView {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var phoneLabel: UILabel!
    @IBOutlet weak var emailLabel: UILabel!

    var viewModel: ContactViewModel? {
        didSet {
            guard let viewModel = viewModel else { return }
            nameLabel.text = viewModel.name
            phoneLabel.text = viewModel.phone
            emailLabel.text = viewModel.email
        }
    }
}

ViewModel: This is a view model class that represents a contact in a way that is suitable for the view. It has properties that mirror the properties of the model, but with any necessary transformations or computed properties. It also has an initializer that receives a Contact instance, it's used to create a new viewModel.

In this example, the ViewModel is responsible for handling the logic related to the presentation of the data, such as formatting or validation, and also for handling any user interactions that might affect the model. The view is responsible for displaying the data and it's updated by the viewModel. The model represents the data and business logic of the application.

// ViewModel

class ContactViewModel {
    var contact: Contact

    var name: String {
        return contact.name
    }

    var phone: String {
        return contact.phone
    }

    var email: String {
        return contact.email
    }

    init(contact: Contact) {
        self.contact = contact
    }
}

Differences

One of the main differences between MVC and MVVM is that in MVC, the controller is responsible for handling user interaction and updating the model and the view, while in MVVM the view-model is responsible for handling user interaction and updating the model and the view. This separation allows for a clear separation of concerns, making the code more maintainable and testable. MVVM also allows for a cleaner separation of concerns between the UI and the business logic, making it easier to test and change the application.

In summary

MVC and MVVM are both design patterns that are commonly used in iOS development to structure the code of an iOS application. They both separate the concerns of an application, but MVVM provides a cleaner separation of concerns between the UI and the business logic, making it easier to test and change the application, and allowing for a clear separation of concerns, making the code more maintainable and testable. Both patterns have their own pros and cons and the best approach will depend on the specific needs of the project and the team working on it.