RxSwift / RxCocoa的以下示例代码有什么作用?

时间:2016-01-07 12:20:55

标签: swift rx-swift

我试图详细了解

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

来自WikipediaSearchViewController.swift第47-64行。 我试图提取参数来查看具体的类型签名,但重写为

    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'使用类型'的参数列表(String,cellType:UITableViewCell.Type)'

表示driveArg1和

  

表达式的类型是不明确的,没有更多的上下文

表示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 {}

但是在这一点上,Swift语法对我来说是难以理解的。任何人都可以解释签名以及代码中发生的事情吗?

1 个答案:

答案 0 :(得分:4)

这里,由于缺乏上下文,Swift编译器无法推断driveArg1driveArg2的类型。当在drive()调用中内联使用时,编译器可以获得更多关于每个参数类型的线索,并且我们最终不需要为这些类型添加注释。

考虑到这一点,让我们尝试为这两个变量添加类型注释。

首先,我们将使用swift 2.2更新rx_itemsWithCellIdentifier的签名,删除令人困惑的currying语法并添加通用注释

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

的类型

这是我们传递给curriedArgument的{​​{1}}的论据,并且是我们在应用drive()后传递给rx_itemsWithCellIdentifier的论据。因此,它需要匹配(source: O)

此类型定义中有两个未知,(Int, S.Generator.Element, Cell) -> VoidS.Generator.Element。它们是通用的,所以我们需要弄清楚它们是什么。

  • Cell很简单,这是我们要配置的单元格类型,Cell
  • WikipediaSearchCell有点困难,但我们可以轻松搞清楚。我们从S.Generator.Element得到序列的类型是我们在源元素的尖括号之间找到的类型。在我们的示例中,source(O.E == S)的类型为temp1。因此,Observable<[SearchResultViewModel]>的类型为S,因此[SearchResultViewModel]将为S.Generator.Element

好,我们现在有SearchResultViewModel的签名:

driverArg2

为简化接下来的内容,我们为其定义(Int, SearchResultViewModel, WikipediaSearchCell) -> Void

typealias

我们现在可以定义typealias CellConfigurator = (Int, SearchResultViewModel, WikipediaSearchCell) -> Void

driveArg2

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

的类型

现在driveArg1已经不在了,找出类型driveArg2变得更容易了。它只是driveArg1的返回类型,替换了通用部分

rx_itemsWithCellIdentifier

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

随着所有这些的扩展,drive的类型签名有望更有意义:

drive