【问题标题】:RxSwift - optional issue on binding to tableViewRxSwift - 绑定到 tableView 的可选问题
【发布时间】:2018-04-03 17:35:15
【问题描述】:

我有一个 UITableView 和一个 users 变量,其签名如下:

let users: Variable<[User]?> = Variable<[User]?>(nil)

当我尝试在 UITableView 中绑定这组用户时,我收到了错误 Generic parameter 'Self' could not be inferred。这仅在我观察 Optional 类型时发生。为什么会这样?这种情况的解决方法是什么?

这是我的做法的一个例子:

private func bind() {
    // Does not compile: Generic parameter 'Self' could not be inferred
    users.asObservable().bind(to:
        tableView.rx.items(cellIdentifier: "UserCell",
            cellType: UITableViewCell.self)) { (index, user, cell) in
            // Cell setup.
    }.disposed(by: disposeBag)
}

【问题讨论】:

  • 你为什么不用filterNil()

标签: ios swift generics optional rx-swift


【解决方案1】:

您看到此错误是因为编译器无法推断Optional 变量users 的类型,这些变量传递给以下函数,这些函数适用于泛型并且需要能够推断类型。

Swift 中的Optional 实际实现如下所示。我猜如果Optional 可能是nil aka .none,编译器无法推断方法的类型,例如itemsbind(to:) 适用于泛型。

public enum Optional<Wrapped> : ExpressibleByNilLiteral {

    /// The absence of a value.
    ///
    /// In code, the absence of a value is typically written using the `nil`
    /// literal rather than the explicit `.none` enumeration case.
    case none

    /// The presence of a value, stored as `Wrapped`.
    case some(Wrapped)

    /// Creates an instance that stores the given value.
    public init(_ some: Wrapped)
    //...
}

解决方法 1.):您可以使用 filterNil() (RxOptionals lib) 来避免该问题。

private func bind() {
    users.asObservable().filterNil().bind(to:
        tableView.rx.items(cellIdentifier: "UserCell",
            cellType: UITableViewCell.self)) { (index, user, cell) in
            // Cell setup.
    }.disposed(by: disposeBag)
}

解决方法 2.):将 users 设为非可选。如果您没有用户,只需将一个空数组设置为值。

let users: Variable<[User]> = Variable<[User]>([])

解决方法 3.):在 map 函数中使用 Nil-Coalescing Operator ?? 类似

private func bind() {
    users.asObservable().map { optionalUsers -> [User] in 
          return optionalUsers ?? [] 
        }
        .bind(to:
        tableView.rx.items(cellIdentifier: "UserCell",
            cellType: UITableViewCell.self)) { (index, user, cell) in
            // Cell setup.
    }.disposed(by: disposeBag)
}

旁注Variable 在最新版本的 RxSwift 中已弃用

仅供参考:

items的实现

public func items<S: Sequence, Cell: UITableViewCell, O : ObservableType>
    (cellIdentifier: String, cellType: Cell.Type = Cell.self)
    -> (_ source: O)
    -> (_ configureCell: @escaping (Int, S.Iterator.Element, Cell) -> Void)
    -> Disposable
    where O.E == S {
    return { source in
        return { configureCell in
            let dataSource = RxTableViewReactiveArrayDataSourceSequenceWrapper<S> { (tv, i, item) in
                let indexPath = IndexPath(item: i, section: 0)
                let cell = tv.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! Cell
                configureCell(i, item, cell)
                return cell
            }
            return self.items(dataSource: dataSource)(source)
        }
    }
}

bind(to:)的实现

public func bind<O: ObserverType>(to observer: O) -> Disposable where O.E == E {
    return self.subscribe(observer)
}

【讨论】:

  • 最适用的解决方法是第一个,因为我的用户对象是Mappable(ObjectMapper)并且没有没有参数的初始化程序。不知道filterNil 功能。重要的是要知道它来自 RxOptionals 库。
  • @juniorgarcia 我根据您的建议更新了我的答案,并提供了第三种解决方法
【解决方案2】:

在没有可选类型的情况下,我遇到了同样的错误。发生这种情况是因为我在 UITableView 中使用了 UICollectionViewCell 子类。

【讨论】:

    猜你喜欢
    • 2018-03-14
    • 2013-03-31
    • 1970-01-01
    • 2016-08-23
    • 1970-01-01
    • 1970-01-01
    • 2017-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多