2016-01-07 13 views
11

Próbuję zrozumieć szczegółowoCo robi następujący przykładowy kod z RxSwift/RxCocoa?

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

z linii WikipediaSearchViewController.swift 47-64. Starałem się wyodrębnić argumenty, aby spojrzeć na konkretne podpisami typu, ale przepisać do

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) 

daje

nie może powoływać „rx_itemsWithCellIdentifier” z listy argumentów typu „(String, cellType: UITableViewCell.Type)”

dla driveArg1 i

rodzaj wyrażenia jest niejednoznaczny bez kontekstu

dla driveArg2.

Podpisy drive i rx_itemsWithCellIdentifier

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

ale w tym momencie składnia Swift jest cholernie niezrozumiałe dla mnie. Czy ktoś może wyjaśnić podpisy i co dzieje się w kodzie?

+0

I m zrozumiał, że istnieje rodzaj rodzajowego niedopasowania typu. I nie może znaleźć ogólnego rodzaju (S: SequenceType) w parametrach funkcji rx_itemsWithCellIdentifier. –

Odpowiedz

4

Tutaj kompilator Swift nie może wywnioskować typu driveArg1 i driveArg2 z powodu braku kontekstu. Kiedy jest używany inline w wywołaniu drive(), kompilator ma więcej wskazówek od tego, jaki może być typ każdego parametru, a my nie potrzebujemy adnotacji dla tych typów.

Biorąc to pod uwagę, spróbujmy dodać adnotację typu dla tych dwóch zmiennych.

Po pierwsze, będziemy aktualizować podpis rx_itemsWithCellIdentifier z szybkim 2.2 na uwadze, usuwając mylące składni currying a także dodanie rodzajowe adnotacje

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 

Rodzaj driveArg2

To argument mijamy do curriedArgument z drive() i będzie argumentem, który przekazujemy do rx_itemsWithCellIdentifier po zastosowaniu (source: O). Dlatego musi on być zgodny z (Int, S.Generator.Element, Cell) -> Void

Istnieją dwa nieznane w tej definicji typu, S.Generator.Element i Cell. Są ogólne, więc musimy dowiedzieć się, jakie one są.

  • Cell jest łatwe, jest to rodzaj ogniwa chcemy skonfigurować, tutaj WikipediaSearchCell.
  • S.Generator.Element jest nieco trudniejsze, ale możemy to łatwo zrozumieć. Otrzymujemy od O.E == S, że typ sekwencji znajduje się pomiędzy nawiasem ostrym naszego elementu źródłowego. W naszym przypadku źródło (temp1) jest typu Observable<[SearchResultViewModel]>.Więc S „s typ jest [SearchResultViewModel] stąd S.Generator.Element będzie SearchResultViewModel

Dobra, teraz mamy podpis driverArg2:

(Int, SearchResultViewModel, WikipediaSearchCell) -> Void 

Aby uprościć, co będzie dalej, pozwala zdefiniować typealias bo

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

Możemy teraz zdefiniować driveArg2

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

Rodzaj driveArg1

Teraz driveArg2 jest na uboczu, zastanawianie się typ driveArg1 od staje się łatwiejsze. Jest to po prostu rodzaj powrotu rx_itemsWithCellIdentifier, przy czym część generic zastąpiony

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

drive podpisu

Z tym wszystkim rozbudowany, podpis typu dla drive nadzieją większy sens:

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