I'm trying to understand in detail
.drive(resultsTableView.rx_itemsWithCellIdentifier("WikipediaSearchCell",
cellType: WikipediaSearchCell.self))
{ (_, viewModel, cell) in
cell.viewModel = viewModel
}
from WikipediaSearchViewController.swift lines 47-64. I've tried to extract the arguments to look at the concrete type signatures, but a rewrite to
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)
gives
cannot invoke 'rx_itemsWithCellIdentifier' with an argument list of type '(String, cellType: UITableViewCell.Type)'
for driveArg1 and
type of expression is ambiguous without more context
for driveArg2.
The signatures of drive
and rx_itemsWithCellIdentifier
are
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 {}
but at this point Swift syntax is darn incomprehensible for me. Can anyone explain the signatures and what happens in the code?
Here, Swift compiler cannot infer the type of driveArg1
and driveArg2
because of a lack of context. When used inline within the drive()
call, the compiler have more clues as of what the type of each parameter can be, and we end-up not needing to annotate for those types.
Taking this into account, lets try to add type annotation for those two variables.
First, we'll update the signature of rx_itemsWithCellIdentifier
with swift 2.2 in mind, removing the confusing currying syntax and also adding the generic annotations
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
It's the argument we pass to curriedArgument
of drive()
, and will be the argument we pass to rx_itemsWithCellIdentifier
after applying (source: O)
. Thus, it needs to match (Int, S.Generator.Element, Cell) -> Void
There are two unknown in this type definition, S.Generator.Element
and Cell
. They are generic, so we need to figure out what they are.
Cell
is easy, it's the type of the cell we want to configure, here WikipediaSearchCell
. S.Generator.Element
is a bit harder, but we can figure it out pretty easily. We get from OE == S
that the type of the sequence is the type we find between the angle bracket of our source element. In our case, source ( temp1
) is of type Observable<[SearchResultViewModel]>
. So S
's type is [SearchResultViewModel]
hence, S.Generator.Element
will be SearchResultViewModel
Good, we now have the signature of driverArg2
:
(Int, SearchResultViewModel, WikipediaSearchCell) -> Void
To simplify what comes next, lets define a typealias
for it
typealias CellConfigurator = (Int, SearchResultViewModel, WikipediaSearchCell) -> Void
We can now define driveArg2
let driveArg2: CellConfigurator = { (_, viewModel: SearchResultViewModel, cell: WikipediaSearchCell) in
cell.viewModel = viewModel
}
driveArg1
Now that driveArg2
is out of the way, figuring out the type driveArg1
of gets easier. It is simply the return type of rx_itemsWithCellIdentifier
, with the generic portion replaced
typealias DriveArg2Type = (source: Observable<[SearchResultViewModel]>) -> (CellConfiguration) -> Disposable
drive
signature With all this expanded, the type signature for drive
hopefully makes more sense:
drive(Self -> R1 -> R2, curriedArgument: R1) -> R2
// where
Self = Observable<[SearchResultViewModel]>
R1 = CellConfigurator
R2 = Disposable
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.