2017-08-09 4 views
1

ItemDetailViewModel est initialisé avec la signature suivante:Voir le modèle injection de dépendances

init(item: Item, didPressButton: Observable<Void>, api: FirebaseAPI) 

Il est initialisé dans ItemDetailViewController, qui obtient un Item de Segue du contrôleur source. Je me rends compte que ItemDetailViewController est techniquement le View, donc il ne devrait pas avoir Item comme une propriété stockée. Sinon, comment transférer Item à ItemDetailViewModel? Cela signifie également que ItemListViewController ne doit pas avoir une propriété stockée selectedItem à utiliser dans prepareFor(segue:).

solution potentielle

Alors, quand un CollectionView Cell est taraudés ItemListViewController (contrôleur de source), il doit déclencher ItemListViewModel par la liaison à stocker Item, puis perform segue. Pendant ce temps, dans prepareForSegue j'utilise ItemListViewModel pour initialiser ItemDetailViewModel avec Item. Ok .. Ça pourrait marcher.

Comment puis-je gérer les pressions sur les boutons, qui changent d'image à chaque pression? à travers une fonction?

Quelle est la bonne façon d'initialiser view models et inject dependencies?

+1

Votre modèle de vue ne devrait pas être concerné par le bouton robinets C'est à la vue ou au contrôleur de vue de traiter. Vous devez créer le 'ItemDetailViewModel' comme vous le proposez et le passer à' ItemDetailViewController' via le segue. Lorsqu'un bouton est appuyé, le contrôleur de vue reçoit cette notification et met à jour le 'ItemDetailViewModel'. – Paulw11

+0

Ok, donc quand je m'inscris à un bouton taps, à l'intérieur du bloc d'abonnement j'appelle une méthode sur mon viewModel pour gérer le comportement. Merci –

+0

Le 'didPressButton' observable n'est pas une touche du bouton. Il s'agit plutôt d'une «raison pour laquelle le modèle de vue doit faire quelque chose», ce qui peut être dû ou non à un bouton. Par conséquent, le modèle de vue n'est pas concerné par les pressions de bouton dans cette question. Il est préférable de simplement passer le bouton observable directement au modèle de vue car cela supprimera la logique du contrôleur de vue. –

Répondre

0

Vous avez un objet qui nécessite trois données à construire, mais l'une des données provient d'une source différente des deux autres. C'est le bon moment pour utiliser des fonctions d'ordre supérieur.

struct ItemDetailViewModel { 
    static func factory(item: Item, api: FirebaseAPI) -> (_ action: Observable<Void>) -> ItemDetailViewModel { 
     return { action in 
      return ItemDetailViewModel(item: item, didPressButton: action, api: api) 
     } 
    } 
} 

Votre contrôleur de vue accepterait le résultat de cette fonction:

class ItemDetailViewController: UIViewController { 
    var viewModelFactory: (Observable<Void>) -> ItemDetailViewController = { _ in fatalError("factory called before provided.") } 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     let viewModel = viewModelFactory(myButton.rx.tap.asObservable()) 
     // bind output to view model 
    } 
} 

Ensuite, dans votre contrôleur Préparons vue précédente pour Segue:

if let controller = segue.destinationViewController as? ItemDetailViewController { 
    controller.viewModelFactory = ItemDetailViewModel.factory(item: anItem, api: api) 
}