使用Rx编程将JSON响应映射到对象(Moya)

时间:2016-04-09 12:46:03

标签: ios swift networking rx-swift moya

我目前正在尝试学习Rx编程。我发现Moya很有趣,并且一直在尝试实现一个简单的网络请求,然后将其映射到对象,然后我可以使用它来填充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

所以我想知道是否有人可以帮助我了解为什么我无法将响应变成对象。感谢。

=======

我尝试过更新pod但它仍然无法正常工作。这是我将它绑定到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 个答案:

答案 0 :(得分:1)

它不起作用的原因是从服务器检索的JSON返回字典而不是数组。你要解析的阵列是在#34; train&#34;键入该词典。本教程中使用的Moya-ModelMapper也包含此用法的方法。您只需要在keyPath:方法中传递第二个参数mapArrayOptional()

所以你的问题的答案是替换:
.mapArrayOptional(Train.self)

.mapArrayOptional(Train.self, keyPath: "trains")