【问题标题】:What does the following example code from RxSwift/RxCocoa do?以下来自 RxSwift/RxCocoa 的示例代码有什么作用?
【发布时间】:2016-01-07 12:20:55
【问题描述】:

我正在尝试详细了解

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

给了

无法使用“(String, cellType: UITableViewCell.Type)”类型的参数列表调用“rx_itemsWithCellIdentifier”

对于 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 语法对我来说是不可理解的。谁能解释一下签名和代码中发生了什么?

【问题讨论】:

  • 我了解到存在某种泛型类型不匹配。并且在 rx_itemsWithCellIdentifier 函数参数中无法确定 (S: SequenceType) 的泛型类型。

标签: swift rx-swift


【解决方案1】:

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

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

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

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 的类型

这是我们传递给drive()curriedArgument 的参数,也是我们在应用(source: O) 后传递给rx_itemsWithCellIdentifier 的参数。因此,它需要匹配(Int, S.Generator.Element, Cell) -&gt; Void

此类型定义中有两个未知数,S.Generator.ElementCell。它们是通用的,所以我们需要弄清楚它们是什么。

  • Cell很简单,就是我们要配置的cell的类型,这里WikipediaSearchCell
  • S.Generator.Element 有点难,但我们可以很容易地弄清楚。我们从O.E == S 得到序列的类型是我们在源元素的尖括号之间找到的类型。在我们的例子中,源 (temp1) 的类型是 Observable&lt;[SearchResultViewModel]&gt;。所以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 的类型签名希望更有意义:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-21
    • 2018-05-31
    • 1970-01-01
    • 2015-11-19
    • 2019-11-19
    相关资源
    最近更新 更多