Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxSwift request for each iteration of array

I'm using RxSwift to fetch some network data and I'm having trouble with performing a request for each iteration of an array. This was my idea:

  • I have an API endpoint that returns an array of Objs which doesn't contain location data. Then I would loop through the array of Objs and for each get the location details with the Obj id. Something like this:

(code simplified)

var arrayObj = networkClient.request(getObjsEndpoint)
        .fetchObjLocationDetails(withNetworkClient: networkClient)
  • And the fetchObjLocationDetails() would be something like:

(code simplified)

extension ObservableType where E == [Obj]? {
func fetchObjsLocationDetails(withNetworkClient networkClient: NetworkClient) -> Observable<[Obj]?> {
        return flatMap { Objs -> Observable<[Obj]?> in
            guard let unwrappedObjs = Objs as [Obj]? else { return Observable.just(nil) }

            let disposeBag = DisposeBag()
            var populatedObjs = [Obj]()

            unwrappedObjs.forEach { obj in
                let getLocationDetailsEndpoint = WeDriveParkAPI.getLocation(id: String(obj.id))

                networkClient.request(getLocationDetailsEndpoint)
                    .observeOn(MainScheduler.instance)
                    .subscribe(onNext: { json in
                        guard let populatedObj = Obj.fromJSON(json) as Obj? else { return }

                        populatedObjs += [populatedObj]
                        }, onError:{ e in

                    }).addDisposableTo(disposeBag)
            }
            return Observable.just(populatedObjs)
        }
    }
}

This solution is not really working because the code doesn't even go inside the subscribe next closure.

Please have in mind I'm new to both Swift and RxSwift programming so be gentle :) Any help would be greatly appreciated.

like image 611
Bruno Morgado Avatar asked Feb 12 '16 10:02

Bruno Morgado


1 Answers

Instead of making custom operator you can use built-in.

networkClient.request(getObjsEndpoint)
.map({ (objs:[Obj]?) -> [Obj] in
    if let objs = objs {
        return objs
    } else {
        throw NSError(domain: "Objs is nil", code: 1, userInfo: nil)
    }
})
.flatMap({ (objs:[Obj]) -> Observable<[Obj]> in
    return objs.toObservable().flatMap({ (obj:Obj) -> Observable<Obj> in
        let getLocationDetailsEndpoint = WeDriveParkAPI.getLocation(id: String(obj.id))
        return self.networkClient.request(getLocationDetailsEndpoint)
        .map({ (obj:Obj?) -> Obj in
            if let obj = obj {
                return obj
            } else {
                throw NSError(domain: "Obj is nil", code: 1, userInfo: nil)
            }
        })
    }).toArray()
})
.subscribeNext({ (objs:[Obj]) in
    print("Populated objects:")
    print(objs)
}).addDisposableTo(bag)
like image 116
Evgeny Sureev Avatar answered Nov 01 '22 23:11

Evgeny Sureev