ReactiveCocoa 3: Map signal to value (Swift)

778 views Asked by At

I'm pretty new to ReactiveCocoa 3 and Swift and have the following code example. I'd like to map the signal returned from the map function to receive the JSON values in the start function at the end.

At the moment I'm passing through a Signal<JSON, NSError> which I observe inside the start function. Is there a better solution to this?

import Foundation
import ReactiveCocoa
import SwiftyJSON

class SearchViewModel {

    let results = MutableProperty<[MyModel]>([])
    let searchText = MutableProperty<String>("")

    init() {
        searchText.producer
            |> map { keyword -> Signal<JSON, NSError> in Api().get("search/\(keyword)") }
            |> start(
                next: { signal in
                    signal
                        |> observe(
                            next: { jsonArray in
                                let models = jsonArray.arrayValue.map(modelAdapter)

                                self.results.put(models)
                            }
                    )
                }
        )

    }

}

Update:

It turned out the problem was my understanding of ReactiveCocoa. See my answer below.

1

There are 1 answers

0
schickling On BEST ANSWER

It turned out my Api.get() function should return a SignalProducer instead of a Signal. With this adjustment I ended up with a solution like this:

let keywordToJson: SignalProducer<String, NSError>  -> SignalProducer<JSON, NSError> = flatMap(.Concat) { keyword in Api().get("search/\(keyword)" }

searchText.producer
    |> mapError { _ in NSError() }
    |> keywordToJson
    |> start(
        next: { jsonArray in
            let models = jsonArray.arrayValue.map(modelAdapter)

            self.results.put(models)
        }
)

Notes:
(1) At the moment it seems to be necessary that you have to give the compiler some hints about the type of the flatMap function.
(2) You also need to remap the error of your properties producer from NoError to NSError.