Sono uno sviluppatore iOS e sono colpevole di avere Massive View Controller nei miei progetti, quindi ho cercato un modo migliore per strutturare i miei progetti e ho incontrato MVVM (Model-View -ViewModel) architettura. Ho letto molto MVVM con iOS e ho un paio di domande. Spiegherò i miei problemi con un esempio.Utilizzo di MVVM in iOS
Ho un controller di visualizzazione chiamato LoginViewController
.
LoginViewController.swift
import UIKit
class LoginViewController: UIViewController {
@IBOutlet private var usernameTextField: UITextField!
@IBOutlet private var passwordTextField: UITextField!
private let loginViewModel = LoginViewModel()
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func loginButtonPressed(sender: UIButton) {
loginViewModel.login()
}
}
Non ha una classe modello. Ma ho creato un modello di visualizzazione chiamato LoginViewModel
per inserire la logica di convalida e le chiamate di rete.
LoginViewModel.swift
import Foundation
class LoginViewModel {
var username: String?
var password: String?
init(username: String? = nil, password: String? = nil) {
self.username = username
self.password = password
}
func validate() {
if username == nil || password == nil {
// Show the user an alert with the error
}
}
func login() {
// Call the login() method in ApiHandler
let api = ApiHandler()
api.login(username!, password: password!, success: { (data) -> Void in
// Go to the next view controller
}) { (error) -> Void in
// Show the user an alert with the error
}
}
}
La mia prima domanda è semplicemente è la mia implementazione MVVM corretta? Ho questo dubbio perché, ad esempio, inserisco l'evento di tocco del pulsante di accesso (
loginButtonPressed
) nel controller. Non ho creato una vista separata per la schermata di accesso perché ha solo un paio di campi di testo e un pulsante. È accettabile che il controller abbia metodi evento legati agli elementi dell'interfaccia utente?La mia prossima domanda riguarda anche il pulsante di accesso. Quando l'utente tocca il pulsante, i valori del nome utente e della password devono essere passati a LoginViewModel per la convalida e, in caso di esito positivo, alla chiamata API. La mia domanda su come passare i valori al modello di vista. Devo aggiungere due parametri al metodo
login()
e passarli quando li chiamo dal controller di visualizzazione? O dovrei dichiarare le proprietà per loro nel modello di vista e impostare i loro valori dal controller di visualizzazione? Quale è accettabile in MVVM?Prendere il metodo
validate()
nel modello di vista. L'utente dovrebbe essere avvisato se uno di questi è vuoto. Ciò significa che dopo il controllo, il risultato deve essere restituito al controller della vista per intraprendere le azioni necessarie (mostrare un avviso). Stessa cosa con il metodologin()
. Avvisa l'utente se la richiesta fallisce o passa al controller della vista successivo se ha successo. Come posso notificare il controller di questi eventi dal modello di visualizzazione? È possibile utilizzare meccanismi vincolanti come KVO in casi come questo?Quali sono gli altri meccanismi di associazione quando si utilizza MVVM per iOS? KVO è uno. Ma ho letto che non è adatto a progetti più grandi perché richiede un sacco di codice boilerplate (registrando/annullando la registrazione di osservatori, ecc.). Quali sono le altre opzioni? So che ReactiveCocoa è un framework usato per questo, ma sto cercando di vedere se ci sono altri nativi.
Tutti i materiali mi sono imbattuto su MVVM su Internet fornito poca o nessuna informazione su queste parti che sto cercando di chiarire, quindi mi piacerebbe davvero apprezzare le vostre risposte.
È che solo io o qualcun altro non piacciono le richieste di rete fatte anche da un modello di visualizzazione? – SoftDesigner
@SoftDesigner Concordo, è consigliabile non effettuare chiamate di rete nel modello di visualizzazione ma nell'esempio fornito la classe ApiHandler ha estratto correttamente le specifiche su come viene eseguito un accesso. A questo punto è solo una buona ipotesi che ci sia effettivamente una chiamata in rete. L'app potrebbe essere offline e accedere tramite un db locale. Non lo sappiamo e nemmeno il modello di vista (che è come dovrebbe essere). Sarebbe meglio se il tipo di dati per la variabile api fosse un protocollo implementato da ApiHandler. –