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()
}
}