You're actually really close there.
But you can't have RACSignal
s of CGPoint
s, because CGPoint
is not a reference type. Generally, in the ReactiveCocoa 2 world, you get around this by explicitly boxing and unboxing types like NSValue
and doing a fair bit of casting around:
panRecognizer.rac_gestureSignal()
.map({ [unowned self] (pgr: AnyObject!) -> NSValue! in
let pgr = pgr as! UIPanGestureRecognizer
return NSValue(CGPoint: pgr.locationInView(self.someUiView))
}).subscribeNext({[unowned self] locationValue in
let location = locationValue.CGPointValue
self.someNetworkDelegate.updatePosition(location)
})
However, by converting the RACSignal
into a SignalProducer
, you can use the nice types you want. Doing this is... cumbersome, so I use the following helpers:
extension SignalProducer {
func castSignal<T>() -> SignalProducer<T, Error> {
return self.map({ $0 as! T })
}
func cantError() -> SignalProducer<Value, NoError> {
// If we inline this, Swift will try to implicitly return the fatalError
// expression. If we put an explicit return to stop this, it complains
// it can never execute. One is an error, the other a warning, so we're
// taking the coward's way out and doing this to sidestep the problem.
func swallowError(error: Error) -> SignalProducer<Value, NoError> {
fatalError("Underlying signal errored! \(error)")
}
return self.flatMapError(swallowError)
}
}
extension RACSignal {
func cast<T>() -> SignalProducer<T, NoError> {
return self.toSignalProducer().cantError().map({ $0! }).castSignal()
}
}
Obviously you'd need different helpers if you're converting signals that can error, but this works nicely for this example.
With those, you can write your code just like this:
self.reportTapRecognizer.rac_gestureSignal().cast()
.map({ [unowned self] (pgr: UIPanGestureRecognizer) -> CGPoint in
return pgr.locationInView(self.someUiView)
}).startWithNext({ [unowned self] location in
self.someNetworkDelegate.updatePosition(location)
})
Which is basically how you've written it above. Note that the type annotations are required in the map
call so that cast
can infer its return type properly.