2

RXSwiftとMVVMを使ってiPad用のアプリを作っています。

UICollectionView を持つ UIViewController と、dataSource および collectionView のデリゲートとして機能する ViewModel があります。

コレクション セルの機能の一部は、ボタンをタップしてポップオーバーを表示することです。現在、iOS 9 (おそらくそれ以前) の新しいポップオーバー機能では、View Controller 内で通常どおりビューを表示し、popoverPresentationController を変更する必要があります。

さて、私が知る限り、UICollectionViewCell から UIViewController を提示することはできません。理にかなっています。

しかし、これを行う唯一の方法は、ViewController を指すデリゲートを持つことです。

クラス ダイアグラム (添付) を見ると、viewModel はセルのデキュー時にデリゲートを設定する必要があります。これを行うには、ViewModel は、どの ViewController をデリゲートとして設定するかを知る必要があります。これは、viewModel のポイントに反すると確信しています。MVVM (for iOS) によると、ビュー モデルはビュー コントローラーについて認識すべきではありません。ビューコントローラーは、ビューモデルについて知ることができます。

それで私の質問は、MVVMに続いてこれを行うための最良の方法は何ですか? dataSource/Delegate を別のクラスに移動する必要がある場合は、それで十分です。

UML ダイアグラム

4

1 に答える 1

1

ビューモデルは、ボタンがタップされていることをまったく認識すべきではないと思います。タッチ イベントの処理は、ビュー レイヤーに属し、ポップオーバーを表示します。

これは、ビュー モデルがおそらくUICollectionViewDataSource. したがってRootCollectionViewCell、ビューである と結合されます。残念ながら、Apple がこのように設計したため、この結合を避けることは困難UICollectionViewDataSourceです。別のクラスをデータ ソースとして抽出するか、データ ソース メソッドをビュー コントローラー (iOS の MVVM のビュー レイヤーに属します) に残すことができます。

RxCocoa を使用すると、UICollectionViewDataSourceメソッドの実装をまったく回避することさえできます。UICollectionView+Rx拡張子を見てください。RxSwift リポジトリ(コレクション ビューを含むテーブル ビュー セル)にも例があります。

ボタン タップをビュー コントローラーに渡すには、rx_tapObservable を使用してセルのインターフェイスに公開します。Observable次に、ビュー コントローラー (または別のデータ ソース クラス) で結果をサブスクライブできます。

//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)

この回答で説明されているように、セルが再利用されるときに同じ Observable に何度もサブスクライブしないようにする必要があります。そのためcell.disposeBag、上記のコードで が使用されています。disposeBagまた、そのprepareForReuseメソッドでセルを再作成する必要があります。

class RootCollectionViewCell: UICollectionViewCell {

    var disposeBagCell:DisposeBag = DisposeBag()

    ...

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

}
于 2016-04-05T08:13:05.120 に答える