Skip to content

Instantly share code, notes, and snippets.

@robpearson
Last active August 29, 2015 13:59
Show Gist options
  • Save robpearson/10764980 to your computer and use it in GitHub Desktop.
Save robpearson/10764980 to your computer and use it in GitHub Desktop.
User Location Signal
// Location Service
- (RACSignal *)locationSignal {
// NOTE: Location service is a singleton thus no strongify/weakify
// TODO: Review previous service code to add checks on last object to ensure that it's up-to-date and of the correct accuracy.
// TODO: Review how to restart the timer. I'm currently using take: 1 so it's not needed immediately.
RACSignal *locationSignal = [[RACSignal
createSignal:^RACDisposable *(id <RACSubscriber> subscriber) {
[[self rac_signalForSelector:@selector(locationManager:didUpdateLocations:) fromProtocol:@protocol(CLLocationManagerDelegate)] subscribeNext:^(RACTuple *value) {
NSArray *locations = value[1]; // Ignore the location manager
[subscriber sendNext:locations.lastObject];
}];
[[self rac_signalForSelector:@selector(locationManager:didFailWithError:) fromProtocol:@protocol(CLLocationManagerDelegate)] subscribeNext:^(RACTuple *value) {
NSError *error = value[1]; // Ignore the location manager
if (error.domain == kCLErrorDomain && error.code == kCLErrorLocationUnknown) {
return;
}
[subscriber sendError:error];
}];
[self start];
return [RACDisposable disposableWithBlock:^{
[self stop];
}];
}] timeout:10 onScheduler:[RACScheduler scheduler]];
return locationSignal;
}
// View Controller
- (void)bindSignals {
@weakify(self);
...
// Signal subscription never fires.
[self.viewModel.userLocationSignal subscribeNext:^(id x) {
@strongify(self);
CLLocation *location = x;
if (location != nil) {
self.departureStationLabel.text = location.description; // Simple code for now
}
} error:^(NSError *error) {
NSString *errorMessage = error.description;
}];
// View Model
- (void)bindSignals {
@weakify(self);
...
// Trying to refresh the users's location every x interval.
// Location Service provides a constant stream of updates thus the take:1.
self.userLocationSignal = [[RACSignal
interval:30 onScheduler:[RACScheduler scheduler]]
map:^id(id value) {
[[[self.locationService locationSignalWithTimeout:10] take:1]
subscribeNext:^(CLLocation *currentUserLocation) {
return currentUserLocation;
} error:^(NSError *error) {
// TODO: Error Handling
}];
return nil;
}];
}
@robpearson
Copy link
Author

The goal is to obtain the latest value from the locationService every x interval. The locationService.locationSignal provides a constant stream of location updates. This can drain the battery thus the take:1.

I question if building the delegate handling signals within the locationService.locationSignal is a good idea.

@robpearson
Copy link
Author

Updated the MPXTransitDashboardViewModel.userLocationSignal signal creation code. Based on feedback from @kastiglione, the use of concat wouldn't work because the interval signal is infinite. I thought concat would continuously add a new value from the location service signal every time the interval signal fired but this is not correct. So, I've dumbed it down to subscribe to the first location update every x interval.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment