2016-04-04 7 views
1

Ich mache eine App für iPad mit RXSwift und MVVM.Was wäre die richtige MVVM-Architektur für einen UICollectionViewController

Ich habe einen UIViewController mit einem UICollectionView und einem ViewModel, die als dataSource und der Delegate für die CollectionView fungiert.

Ein Teil der Funktionen der Erfassungszellen besteht darin, dass ein Knopf gedrückt wird, um ein Popover anzuzeigen. Jetzt mit der neueren Popover-Funktionalität in iOS 9 (möglicherweise früher) müssen Sie die Ansicht normalerweise innerhalb des View-Controllers präsentieren und den popoverPresentationController ändern.

Nun, soweit ich weiß, Sie sind nicht in der Lage, eine UIViewController von einer UICollectionViewCell zu präsentieren. Macht Sinn.

Aber die einzige Möglichkeit, dies zu tun, wäre, einen Delegaten zu haben, der auf den ViewController zeigt.

Mit Blick auf das Klassendiagramm (im Anhang) müsste das ViewModel den Delegaten beim Entfernen der Zelle einstellen. Um das zu tun, müsste das ViewModel wissen, was ViewController als den Delegaten einstellen soll, von dem ich ziemlich sicher bin, dass es gegen den Punkt des viewModel geht. Laut MVVM (für iOS) sollte das View-Modell den View-Controller nicht kennen. Der View-Controller kann das View-Modell kennen.

Und meine Frage ist, was wäre der beste Weg, dies nach MVVM zu tun? Wenn es erforderlich ist, die dataSource/Delegate in eine andere Klasse zu verschieben, bin ich dafür.

UML Diagram

Antwort

1

denke ich Ansicht Modell der Taste geklopft wird gar nicht bewusst sein sollten. Die Behandlung von Berührungsereignissen gehört zum Ansichtslayer und stellt das Popover dar.

Dies zeigt auch, dass Ihr Ansichtsmodell wahrscheinlich nicht UICollectionViewDataSource sein sollte. So ist es mit RootCollectionViewCell gekoppelt, das ist eine Ansicht. Leider ist diese Kopplung schwer zu vermeiden, da Apple auf diese Weise UICollectionViewDataSource entworfen hat. Sie können entweder eine separate Klasse als Datenquelle extrahieren oder die Datenquellenmethoden im View-Controller belassen (der in MVVM unter iOS zur View-Ebene gehört).

Mit RxCocoa können Sie sogar vermeiden, UICollectionViewDataSource Methoden überhaupt zu implementieren. Werfen Sie einen Blick auf UICollectionView+Rx Erweiterungen. Es gibt auch eine example in RxSwift repository (Tabellenansichtszelle, die eine Sammlungsansicht enthält).

Zum Übergeben der Tastenabgriffe an den View-Controller können Sie rx_tap Observable verwenden und in der Zellschnittstelle anzeigen. Dann können Sie auf die resultierenden Observable im View-Controller (oder in der separaten Datenquellenklasse) abonnieren:

//in the cell class 
var buttonTapped : ControlEvent<Void> { 
    return button.rx_tap 
} 

//in the data source 
cell.buttonTapped.subscribeNext { 
    //show the popover 
}.addDisposableTo(cell.disposeBag) 

Wie in this answer beschrieben, sollten Sie mehrmals auf die gleiche beobachtbare abonnieren möchte vermeiden, wenn die Zelle wiederverwendet wird. Deshalb wird im obigen Code cell.disposeBag verwendet. Sie sollten auch die Zelle in ihrer prepareForReuse Methode neu erstellen:

class RootCollectionViewCell: UICollectionViewCell { 

    var disposeBagCell:DisposeBag = DisposeBag() 

    ... 

    override func prepareForReuse() { 
     disposeBagCell = DisposeBag() 
    } 

} 
Verwandte Themen