RxDataSource(3.0.1)版
RxDataSource 中数据源是如何和绑定的–绑定方法
其中最简单的tableView数据源就是一个无分组的数组,
例子A如下:
let items = Observable.just([
"First Item",
"Second Item",
"Third Item"
])
items
.bind(to: tableView.rx.items) { (tableView, row, element) in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "\(element) @ row \(row)"
return cell
}
.disposed(by: disposeBag)
这里可以看到items作为Observable<[String]>类型的数据源绑定到tableView上,根据后面闭包可以判定出,当tableview刷新时,肯定会调用后面返回cell的闭包,那么可以推断出,rx将这个闭包保存了起来,用到时就会调用。
现在开始分析items.bind(to: tableView.rx.items)……. 是怎么个过程
首先,不要被上面bind(to: )这个形式所迷惑了,其实他的原型是:(Observable+bind 这个文件中)
public func bind<R1, R2>(to binder: (Self) -> (R1) -> R2, curriedArgument: R1) -> R2 {
return binder(self)(curriedArgument)
}
乍一看,很很复杂的样子,<R1, R2> 是泛型约束, R1 R2就是两种类型, 我们将它简化一下:
func bind<R1, R2>(to binder: (Self) -> ((R1) -> R2), curriedArgument: R1) -> R2
-> func bind(binder: 参数A, curriedArgument: 参数B) -> 返回值C
其实就是一个两个参数的函数,不同的是参数A 是一个(Self) -> ((R1) -> R2) 这种类型的function,而,bind的参数B是R1类型的,这里要注意理解 参数A不是一个数,而是一个函数。而且是一个返回值也是函数的函数,即 f(a) -> ( f1(b) -> c ),bind函数执行,会执行传过来的参数A这个函数,而这个函数需要的参数又是 Self(调用者本身)
现在再来看tableView.rx.items是什么鬼:(TableView+Rx 这个文件)
public func items<S: Sequence, O: ObservableType>(_ source: O)
-> (_ cellFactory: @escaping ((UITableView, Int, S.Iterator.Element) -> UITableViewCell))
-> Disposable
where O.E == S {
return { cellFactory in
let dataSource = RxTableViewReactiveArrayDataSourceSequenceWrapper<S>(cellFactory: cellFactory)
return self.items(dataSource: dataSource)(source)
}
}
一看这个函数,感觉更复杂,现在简化它:
func items(_ source: O) -> ((cellFactory: xxx) -> Disposable)
-> f(a) -> ( f1(b) -> c )
这么一看,他就是一个 f(a) -> ( f1(b) -> c) 类型的函数,正好符合bind(to: ) 这个函数的第一个函数要求,而bind(to: )第二个参数就是items .bind(to: tableView.rx.items)后面跟随的闭包
func bind<R1, R2>(to binder: (Self) -> ((R1) -> R2), curriedArgument: R1) -> R2
现在binder这个参数有了,再看curriedArgument参数,他的类型是R1, 这里正好对应的事cellFactory东西,去tableView.rx.items函数定义的地方找cellFactory是什么类型,一看,他是一个函数,也就是一个闭包,所以,书写时将其写成了bind(to:)的尾随闭包形式,不用尾随闭包的形式:
// 等价于:
items.bind(to: tableView.rx.items, curriedArgument: { (tableView, row, element) in
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
cell.textLabel?.text = "\(element) @ row \(row)"
return cell
}).disposed(by: bag)
// 也等价于:
typealias CellFactoryType = ((UITableView, Int, String) -> UITableViewCell)
let cellFactory: CellFactoryType = { (tableView, row, element) in
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
cell.textLabel?.text = "\(element) @ row \(row)"
return cell
}
items.bind(to: tableView.rx.items, curriedArgument: cellFactory).disposed(by: bag)
这样,这个绑定结构方法就清楚了
注意:这里只是针对开头贴出来的例子A,TableView+Rx中 还有其他 items(..)类似方法,但是items(_ source: O)的参数传递并不和该例中一样,向bind(to)传递的并不是items(_ source: O)函数本身,而是items(_ source: O)的返回值