2

Let's say I have a function that returns a SignalProducer<AnyObject?, NSError> and I want to bind the producer to multiple MutableProperty<String>. So, something like this:

let foo = SignalProducer<AnyObject?, NSError>(value: nil)
let someProperty1 = MutableProperty<String>("")
let someProperty2 = MutableProperty<String>("")

someProperty1 <~ foo
    .flatMapError { _ in
        SignalProducer<AnyObject?, NoError>.empty
    }
    .map { _ in
        return "test"
    }

// someProperty2 <~ foo etc...

In order to avoid my function (e.g. some network stuff) being run multiple times I would need to use multicasting. As far as I can tell from the CHANGELOG, startWithSignal is the operator to use for this. However I can't seem to figure out how to do this in a declarative manner.

So, one approach could be to make the binding in the closure of the startWithSignal:

foo.startWithSignal { signal, disposable in
    someProperty1 <~ signal
        .map { _ in
            return "test"
        }

    // someProperty2 <~ signal etc...
}

However this will obviously fail because we need to get rid of the NSError part. Because we're giving a Signal (opposed to a SignalProducer), we cannot use flatMapError (in RAC4, catch in RAC3). And I do not see how mapError can do this for us? Lastly, I'm not even sure that this is the proper way to handle multicasting in RAC3/RAC4?

Any help is much appreciated.

Steffen D. Sommer
  • 2,896
  • 2
  • 24
  • 47

2 Answers2

0

Use flatMapError (and any other operators that must take a SignalProducer argument) before starWithSignal

let fooIgnoreError = foo
    .flatMapError { _ in
        SignalProducer<AnyObject?, NoError>.empty
    }


fooIgnoreError.startWithSignal { signal, disposable in
    someProperty1 <~ signal.map { _ in "test" }
    someProperty2 <~ signal.map { _ in "test2" }
}

If the fooIgnoreError is started only once, your underlying signal producer foo is guaranteed to be started only once too.

Cosyn
  • 4,404
  • 1
  • 33
  • 26
0

I explained how to implement multicasting with an example here.

As for errors, you can make your property AnyProperty<Result<Value, Error>> to be able to forward errors. If you want the signal to terminate upon a failure, you can simply

signal.flatMapError { error in 
    fatalError("Error: \(error)") // or some other form of error handling, or simply ignoring the error?
    return .empty
}
Community
  • 1
  • 1
NachoSoto
  • 1,743
  • 13
  • 17
  • This looks exactly what I was looking for. However, I'm not sure I understand how to multicast and be able to forward errors. Could you elaborate a bit more on this? – Steffen D. Sommer Dec 02 '15 at 06:19
  • I explained that a little bit more here: http://stackoverflow.com/a/34010499/401024. – NachoSoto Dec 02 '15 at 06:48
  • Sorry for not being more clear, but I want the type to stay as `SignalProducer`. The example from this answer maps it into `NoError` and the description from the link will include any errors in the `Next` value. Is it possible to achieve what I want? – Steffen D. Sommer Dec 02 '15 at 08:02