Sobes.tech
Middle

Ispričaj mi o MVVM (Model-View-ViewModel) uzorku.

sobes.tech АИ

Одговор од АИ

MVC (Model-View-Controller).

Komponenta Opis Odgovornost
Model Predstavlja podatke i poslovnu logiku aplikacije. Ne zavisi od View ili ViewModel. Upravljanje podacima, poslovna pravila, interakcija sa serverom/bazom podataka.
View Korisnički interfejs. Prikazuje podatke i prenosi akcije korisnika ViewModel-u. Ne sadrži logiku obrade podataka. Prikaz informacija, obrada događaja korisnika (tapovi, swipe-ovi itd.).
ViewModel Posrednik između Model-a i View-a. Pruža View-u podatke u prikladnom formatu za prikaz i obrađuje akcije korisnika, komunicirajući sa Model-om. Ne zna da li se View koristi ili ne, komunicira samo putem data binding-a. Pretvaranje podataka iz Model-a za View, obrada interakcija korisnika, poslovna logika koja nije povezana sa UI-jem.

Osnovni principi:

  • Data Binding: Povezivanje podataka između View i ViewModel. Kada se podaci u ViewModel-u promene, View se automatski osvežava, i obrnuto.
  • Testability: ViewModel je lako testirati, jer ne zavisi od UI okvira.
  • Separation of Concerns: Jasno razdvajanje uloga komponenti.

Prednosti:

  • Poboljšana testabilnost.
  • Čistije razdvajanje odgovornosti.
  • Olakšava kodnu bazu pri radu sa složenim UI-jem.

Nedostaci:

  • Može biti suvišan za jednostavne aplikacije.
  • Teškoće u implementaciji Data Binding-a bez spoljašnjih okvira (npr. RxSwift, Combine).

Primer strukture:

// 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) godina"
    }

    // Metod za obradu akcija korisnika
    func userTapped() {
        print("Korisnik \(user.name) je tapnut")
        // Moguće interakcije sa Model-om ili drugom logikom
    }
}

// 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 (primer ručne veze)
        nameLabel.text = viewModel.displayName
        ageLabel.text = viewModel.displayAge
    }

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