Sobes.tech
Middle

Tell us about the MVVM (Model-View-ViewModel) pattern.

sobes.tech AI

Answer from AI

MVC (Model-View-Controller).

Component Description Responsibility
Model Represents the data and business logic of the application. It is independent of View or ViewModel. Data management, business rules, interaction with server/database.
View User interface. Displays data and passes user actions to ViewModel. Contains no data processing logic. Displaying information, handling user events (taps, swipes, etc.).
ViewModel Mediator between Model and View. Provides View with data in a display-friendly format and handles user actions, interacting with Model. It does not know whether View is used or not, only communicates through data binding. Transforming data from Model for View, handling user interactions, business logic unrelated to UI.

Main principles:

  • Data Binding: Binding data between View and ViewModel. When data in ViewModel changes, View updates automatically, and vice versa.
  • Testability: ViewModel is easy to test as it does not depend on UI framework.
  • Separation of Concerns: Clear separation of component roles.

Advantages:

  • Improved testability.
  • Cleaner separation of responsibilities.
  • Simplifies codebase when working with complex UI.

Disadvantages:

  • May be excessive for simple applications.
  • Complexity of implementing Data Binding without third-party frameworks (e.g., RxSwift, Combine).

Example structure:

// Model
struct User {
    let name: String
    let age: Int
}

// ViewModel
class UserViewModel {
    private let user: User

    init(user: User) {
        self.user = user
    }

    var displayName: String {
        return user.name
    }

    var displayAge: String {
        return "\(user.age) years"
    }

    // Method to handle user actions
    func userTapped() {
        print("User \(user.name) tapped")
        // Possibly interacts with Model or other logic
    }
}

// View (UIViewController)
class UserViewController: UIViewController {

    private var viewModel: UserViewModel!

    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var ageLabel: UILabel!

    func configure(with viewModel: UserViewModel) {
        self.viewModel = viewModel
        updateUI()
    }

    private func updateUI() {
        // Data Binding (manual example)
        nameLabel.text = viewModel.displayName
        ageLabel.text = viewModel.displayAge
    }

    @IBAction func tapGestureRecognized(_ sender: Any) {
        viewModel.userTapped()
    }
}