How is the data source and binding in RxDataSource-1

How the data source in RxDataSource (3.0.1)
is bound to the data source--binding method
The simplest tableView data source is an ungrouped array.
Example A is as follows: 

        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)

Here you can see that items are bound to the tableView as a data source of type Observable<[String]>. According to the latter closure, it can be determined that when the tableview is refreshed, the latter closure that returns the cell will definitely be called, so it can be inferred that, rx saves this closure and calls it when needed.
    Now start to analyze the process of items.bind(to: tableView.rx.items).......
    First of all, don't be confused by the form of bind(to: ) above, in fact, his prototype is: (Observable +bind this file)

    public func bind<R1, R2>(to binder: (Self) -> (R1) -> R2, curriedArgument: R1) -> R2 {
         return binder(self)(curriedArgument)
    }

At first glance, it looks very complicated. <R1, R2> is a generic constraint, and R1 and R2 are two types. Let's simplify it:

   func bind<R1, R2>(to binder: (Self) -> ((R1) -> R2), curriedArgument: R1) -> R2

-> func bind(binder: 参数A, curriedArgument: 参数B) -> 返回值C

In fact, it is a function with two parameters. The difference is that the parameter A is a function of this type (Self) -> ((R1) -> R2), and the parameter B of bind is of type R1. Pay attention to understanding here. The parameter A is not a number, but a function. And it is a function whose return value is also a function, that is, f(a) -> ( f1(b) -> c ), when the bind function is executed, the function of the passed parameter A will be executed, and the parameter required by this function is Self (The caller itself)
  Now let's see what the hell is tableView.rx.items: (TableView+Rx this file)

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

Looking at this function, it feels more complicated, now simplify it:

   func items(_ source: O) -> ((cellFactory: xxx) -> Disposable)
->       f(a)             ->  (        f1(b)      ->  c         ) 

In this way, it is a function of type f(a) -> ( f1(b) -> c), which just meets the first function requirements of bind(to: ), and bind(to: ) is the second The first parameter is the closure
 func bind<R1, R2>(to binder: (Self) -> ((R1) -> R2), curriedArgument: R1) - followed by items .bind(to: tableView.rx.items ) - > R2
now has the binder parameter, and then look at the curriedArgument parameter, his type is R1, which corresponds to the cellFactory thing, go to the place where the tableView.rx.items function is defined to find what type of cellFactory is, at first glance, he is a A function is also a closure, so it is written as a trailing closure of bind(to:) instead of a trailing closure:

        // 等价于:
        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)

In this way, this binding structure method is clear
 

Note: This is only for the example A posted at the beginning. There are other similar methods of items(..) in TableView+Rx, but the parameter transfer of items(_ source: O) is not the same as in this example, to bind(to ) is not passed the items(_ source: O) function itself, but the return value of items(_ source: O)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325295055&siteId=291194637
Recommended