Отображение JSON-ответа на объекты с использованием Rx-программирования (Moya)

В настоящее время я пытаюсь научиться программированию Rx. Я нашел Мойю заинтригованным и пытался реализовать простой сетевой запрос, который затем сопоставлялся с объектами, которые я затем мог бы использовать для заполнения tableView.

Я следовал этому руководству: http://www.thedroidsonroids.com/blog/ios/rxswift-examples-3-networking/

Я верю, что получаю успешный ответ, когда использую .debug и получить следующий вывод:

2016-04-09 13:29:30.398: MyApi.swift:37 (findRepository) -> subscribed
2016-04-09 13:29:30.400: MyApi.swift:35 (findRepository) -> subscribed
2016-04-09 13:29:32.633: MyApi.swift:35 (findRepository) -> Event Next(Status Code: 20..., Data Length: 5747)
2016-04-09 13:29:32.633: MyApi.swift:35 (findRepository) -> Event Completed

Вот код, который я использую:

let provider: RxMoyaProvider<MyApi>
let repositoryName: Observable<String>

func trackIssues() -> Observable<[Train]> {
    return repositoryName
        .observeOn(MainScheduler.instance)
        .flatMapLatest { name -> Observable<[Train]?> in
            print("Name: \(name)")

            return self.findRepository(name)
        }.replaceNilWith([])
}

internal func findRepository(name: String) -> Observable<[Train]?> {
    print("help")
    return self.provider
        .request(MyApi.Trains(name, "c76a46ce2b3d8685982b/raw/10e86080c3b1beedd46db47f5bb188cc74ce5c78/sample.json"))
        .debug()
        .mapArrayOptional(Train.self)
        .debug()
}

И вот объект, который я пытаюсь сопоставить:

import Mapper

struct Train: Mappable {

    let distance: String
    let eta: String

    init(map: Mapper) throws {
        try distance = map.from("distance")
        try eta = map.from("eta")
    }
}

Я посмотрел на сетевой ответ и мне интересно, нужно ли мне сначала абстрагировать данные "поездов". Я пробовал это, сопоставляя следующий объект без удачи:

import Mapper

struct TrainsResponse: Mappable {

    let trains: String

    init(map: Mapper) throws {
        try trains = map.from("trains")
    }
}

Пожалуйста, найдите пример ответа json здесь: http://pastebin.com/Wvx8d5Lg

Поэтому мне было интересно, может ли кто-нибудь помочь мне понять, почему я не могу превратить ответ в объекты. Благодарю.

=======

Я попытался сделать обновление стручка, и это все еще не работает. Вот где я привязываю его к tableView:

func setupRx() {
    // First part of the puzzle, create our Provider
    provider = RxMoyaProvider<MyApi>()

    // Now we will setup our model
    myApi = MyApi(provider: provider, repositoryName: userName)

    // And bind issues to table view
    // Here is where the magic happens, with only one binding
    // we have filled up about 3 table view data source methods
    myApi
        .trackIssues()
        .bindTo(tableView.rx_itemsWithCellFactory) { (tableView, row, item) in
            let cell = tableView.dequeueReusableCellWithIdentifier("issueCell", forIndexPath: NSIndexPath(forRow: row, inSection: 0))
            cell.textLabel?.text = "Hello"

            print("Hello")

            return cell
        }
        .addDisposableTo(disposeBag)
}

Код внутри привязки (где я установил ячейку) никогда не вызывается. Также, если я поставлю точку останова в своем классе Train mapper, который также никогда не будет вызван.

1 ответ

Решение

Причина, по которой это не работает, заключается в том, что JSON, полученный с сервера, возвращает словарь, а не массив. Массив, который вы хотите проанализировать, находится под ключом "trains" в этом словаре. Moya-ModelMapper, используемый в руководстве, также имеет методы для этого использования. Вам просто нужно передать второй аргумент, keyPath: в mapArrayOptional() метод.

Таким образом, ответ на ваш вопрос заменить:
.mapArrayOptional(Train.self)
с
.mapArrayOptional(Train.self, keyPath: "trains")

Другие вопросы по тегам