RxSwift - 绑定到 tableView 的可选问题

RxSwift - optional issue on binding to tableView

我有一个 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)
}

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

Swift中的一个Optional实际实现如下图。我想如果 Optional 可能是 nil 又名 .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 库)来避免该问题。

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 non-optional。如果您没有用户,只需设置一个空数组作为值。

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

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

中使用了 UICollectionViewCell 子类