I'm really excited by the ReactiveCocoa framework and the potential it has, so I've decided that I'm going to bite the bullet and write my first app using it. In my app, I've already written the various services and delegates, but I now need to 'Reactive-Cocoa-ise' them so that I can get on with actual GUI side of things.
That said, so that I better understand this, I'm writing a simple bit of code just to try out concepts. In this case, writing a wrapper for CLLocationManagerDelegate.
In the actual app, the use case would be this:
startMonitoringSignificantLocationChanges
, locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
), then we also stopMonitoringSignificantLocationChanges
You can see a test harness at https://github.com/ippoippo/reactive-core-location-test
The harness 'works' in that it goes off and fetches the location. However, I'm really concerned I'm doing this in the right way.
Consider this code
RACSignal *fetchLocationSignal = [lmDelegate latestLocationSignal];
RACSignal *locationSignal = [fetchLocationSignal catch:^RACSignal *(NSError *error) {
NSLog(@"Unable to fetch location, going to grab default instead: %@", error);
CLLocation *defaultLocation = [lmDelegate defaultLocation];
NSLog(@"defaultLocation = [%@]", defaultLocation);
// TODO OK, so now what. I just want to handle the error and
// pass back this default location as if nothing went wrong???
return [RACSignal empty];
}];
NSLog(@"Created signal, about to bind on self.locationLabel text");
RAC(self.locationLabel, text) = [[locationSignal filter:^BOOL(CLLocation *newLocation) {
NSLog(@"Doing filter first, newLocation = [%@]", newLocation);
return newLocation != nil;
}] map:^(CLLocation *newLocation) {
NSLog(@"Going to return the coordinates in map function");
return [NSString stringWithFormat:@"%d, %d", newLocation.coordinate.longitude, newLocation.coordinate.latitude];
}];
catch
which then gives me the opportunity to then ask the delegate for a default location. But, I'm then stuck on how to then pass back that default location as a signal? Or do I just change my defaultLocation
method to return a RACSignal
rather than CLLocation
??sendNext
or sendCompleted
? Currently it's coded as sendNext
, but it seems like something that would be done as sendCompleted
. latestLocationSignal
in my delegate into an init method instead?Apologies for the rambling question(s), just seem to be going around in circles in my head.
Updating the answer above to ReactiveCocoa 4 and Swift 2.1:
import Foundation
import ReactiveCocoa
class SignalCollector: NSObject, CLLocationManagerDelegate {
let (signal,sink) = Signal<CLLocation, NoError>.pipe()
let locationManager = CLLocationManager()
func start(){
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
for item in locations {
guard let location = item as CLLocation! else { return }
sink.sendNext(location)
}
}
And to listen the events:
var locationSignals : [CLLocation] = []
signal.observeNext({ newLocation in
locationSignals.append(newLocation)
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With