2016-01-07 7 views
11

私はWikipediaSearchViewController.swiftライン47-64から詳細RxSwift/RxCocoaの次のコード例は何ですか?

.drive(resultsTableView.rx_itemsWithCellIdentifier("WikipediaSearchCell", 
     cellType: WikipediaSearchCell.self)) 
      { (_, viewModel, cell) in 
       cell.viewModel = viewModel 
      } 

に理解しようとしています。 呼び出すことはできません、私は具体的な型シグネチャを見て、引数を抽出しようとしたが、

let temp1 = searchBar.rx_text 
     .asDriver() 
     .throttle(0.3) 
     .distinctUntilChanged() 
     .flatMapLatest { query in 
      API.getSearchResults(query) 
       .retry(3) 
       .retryOnBecomesReachable([], reachabilityService: ReachabilityService.sharedReachabilityService) 
       .startWith([]) // clears results on new search term 
       .asDriver(onErrorJustReturn: []) 
     } 
     .map { results in 
      results.map(SearchResultViewModel.init) 
    } 

    let driveArg1 = resultsTableView.rx_itemsWithCellIdentifier("WikipediaSearchCell", cellType: WikipediaSearchCell.self) 
    let driveArg2 = { (_, viewModel: SearchResultViewModel, cell: WikipediaSearchCell) in 
     cell.viewModel = viewModel 
    } 
    temp1.drive(driveArg1, curriedArgument: driveArg2) 
     .addDisposableTo(disposeBag) 

への書き換えが

を与える「rx_itemsWithCellIdentifier」タイプ「(文字列の引数リストで、 cellType:UITableViewCell.Type「)driveArg1ため

式の種類が文脈なしに曖昧です

for driveArg2 driverx_itemsWithCellIdentifier

署名が

public func drive<R1, R2>(with: Self -> R1 -> R2, curriedArgument: R1) -> R2 {} 

public func rx_itemsWithCellIdentifier(cellIdentifier: String, cellType: Cell.Type = Cell.self)(source: O)(configureCell: (Int, S.Generator.Element, Cell) -> Void) -> Disposable {} 

ですが、この時点でスウィフト構文は、私にとってとても不可解です。誰でも署名を説明でき、コードで何が起こるのですか?

+0

:それは、一般的な部分は、これが拡大し、すべてで

typealias DriveArg2Type = (source: Observable<[SearchResultViewModel]>) -> (CellConfiguration) -> Disposable 

drive署名

を交換して、単にrx_itemsWithCellIdentifierの戻り値の型である、driveのための型シグネチャは、うまくいけば、より理にかなっていますある種のジェネリック型の不一致があることを理解していました。また、rx_itemsWithCellIdentifier関数のパラメータには、汎用タイプの(S:SequenceType)がありません。 –

答えて

4

ここで、Swiftコンパイラはコンテキストの不足のためにdriveArg1driveArg2のタイプを推論できません。 drive()コールの中でインラインで使用されると、コンパイラは各パラメータのタイプが何であるかをより多くの手がかりを持っており、これらのタイプにアノテーションを付ける必要はありません。

これを考慮に入れて、これらの2つの変数にタイプ注釈を追加しようとします。

まず、我々はそれが我々が通過引数の混乱カリー化構文を削除しても

public func rx_itemsWithCellIdentifier 
    <S: SequenceType, Cell: UITableViewCell, O : ObservableType where O.E == S> 
    (cellIdentifier: String, cellType: Cell.Type = Cell.self) 
    -> (source: O) 
    -> (configureCell: (Int, S.Generator.Element, Cell) -> Void) 
    -> Disposable 

タイプdriveArg2

の一般的な注釈を追加して、心の中で迅速2.2でrx_itemsWithCellIdentifierの署名を更新しますcurriedArgumentdrive()になり、(source: O)を適用した後にrx_itemsWithCellIdentifierに渡す引数になります。したがって、一致する必要があります(Int, S.Generator.Element, Cell) -> Void

この型定義では、2つの不明な点があります。S.Generator.ElementCellです。彼らは一般的なので、彼らが何であるか把握する必要があります。

  • Cellは、それは我々がここでWikipediaSearchCell、設定したいセルのタイプです、簡単です。
  • S.Generator.Elementはもう少し難しいですが、わかりやすくわかります。 O.E == Sから、シーケンスの型はソース要素の角括弧の間にある型であることがわかります。私たちの場合、ソース(temp1)のタイプはObservable<[SearchResultViewModel]>です。だから、Sのタイプが故に[SearchResultViewModel]で、S.Generator.ElementSearchResultViewModel

良いだろう、我々は今driverArg2の署名を持っている:

(Int, SearchResultViewModel, WikipediaSearchCell) -> Void 

次に来るもの簡略化するために、

ため typealiasを定義することができます
typealias CellConfigurator = (Int, SearchResultViewModel, WikipediaSearchCell) -> Void 

ここで定義できますdriveArg2

let driveArg2: CellConfigurator = { (_, viewModel: SearchResultViewModel, cell: WikipediaSearchCell) in 
    cell.viewModel = viewModel 
} 

タイプ今driveArg2が容易になるの種類driveArg1を考え出す、道の外であること。私は「

drive(Self -> R1 -> R2, curriedArgument: R1) -> R2 
// where 
Self = Observable<[SearchResultViewModel]> 
R1 = CellConfigurator 
R2 = Disposable 

関連する問題