2016-01-07 5 views
11

sto cercando di capire in dettaglioCosa fa il seguente codice di esempio da RxSwift/RxCocoa?

.drive(resultsTableView.rx_itemsWithCellIdentifier("WikipediaSearchCell", 
     cellType: WikipediaSearchCell.self)) 
      { (_, viewModel, cell) in 
       cell.viewModel = viewModel 
      } 

dalle linee WikipediaSearchViewController.swift 47-64. Ho cercato di estrarre gli argomenti per guardare le firme tipo concreto, ma una riscrittura per

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) 

non può invocare la 'rx_itemsWithCellIdentifier' con una lista di argomenti di tipo '(String, tipo di cellule: UITableViewCell.Type)'

per driveArg1 e

tipo di espressione è ambiguo senza più contesto

per driveArg2.

Le firme di drive e rx_itemsWithCellIdentifier sono

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

ma a questo punto la sintassi Swift è maledettamente incomprensibile per me. Qualcuno può spiegare le firme e cosa succede nel codice?

+0

I' Ho capito che esiste una sorta di disallineamento di tipo generico. E non è possibile capire il tipo generico di (S: SequenceType) nei parametri della funzione rx_itemsWithCellIdentifier. –

risposta

4

Qui, il compilatore Swift non può inferire il tipo di driveArg1 e driveArg2 a causa di una mancanza di contesto. Se utilizzato in linea all'interno della chiamata drive(), il compilatore ha più indizi su quale possa essere il tipo di ciascun parametro e alla fine non abbiamo bisogno di annotare per questi tipi.

Tenendo conto di ciò, cerchiamo di aggiungere l'annotazione del tipo per queste due variabili.

In primo luogo, aggiorneremo la firma di rx_itemsWithCellIdentifier con rapido 2.2 in mente, eliminando la sintassi accattivarsi confusa e anche aggiungendo le annotazioni generiche

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 

Tipo di driveArg2

E 'l'argomento passiamo a curriedArgument di drive() e sarà l'argomento che passiamo a rx_itemsWithCellIdentifier dopo l'applicazione di (source: O). Quindi, deve corrispondere a (Int, S.Generator.Element, Cell) -> Void

Ci sono due sconosciuti in questa definizione di tipo, S.Generator.Element e Cell. Sono generici, quindi dobbiamo capire quali sono.

  • Cell è facile, è il tipo di cellule che vogliamo configurare, qui WikipediaSearchCell.
  • S.Generator.Element è un po 'più difficile, ma possiamo capirlo abbastanza facilmente. Otteniamo da O.E == S che il tipo della sequenza è il tipo che troviamo tra la parentesi angolare del nostro elemento sorgente. Nel nostro caso, la fonte (temp1) è di tipo Observable<[SearchResultViewModel]>.Così S 's tipo è [SearchResultViewModel] quindi, S.Generator.Element sarà SearchResultViewModel

Bene, ora abbiamo la firma del driverArg2:

(Int, SearchResultViewModel, WikipediaSearchCell) -> Void 

Per semplificare ciò che viene dopo, permette di definire un typealias per esso

typealias CellConfigurator = (Int, SearchResultViewModel, WikipediaSearchCell) -> Void 

Possiamo ora definire driveArg2

let driveArg2: CellConfigurator = { (_, viewModel: SearchResultViewModel, cell: WikipediaSearchCell) in 
    cell.viewModel = viewModel 
} 

Tipo di driveArg1

Ora che driveArg2 è fuori strada, cercando di capire il tipo di driveArg1 diventa più facile. E 'semplicemente il tipo di ritorno di rx_itemsWithCellIdentifier, con la parte generica sostituito

typealias DriveArg2Type = (source: Observable<[SearchResultViewModel]>) -> (CellConfiguration) -> Disposable 

drive firma

Con tutto questo espansa, la firma tipo per drive rende spera più senso:

drive(Self -> R1 -> R2, curriedArgument: R1) -> R2 
// where 
Self = Observable<[SearchResultViewModel]> 
R1 = CellConfigurator 
R2 = Disposable