Best Reactive - Cocoa for writing CLLocationManagerDelegate, which rarely selects a location

Background

I really care about the ReactiveCocoa infrastructure and the potential that I have, so I decided that I would bite the bullet and write my first application using it. In my application, I have already written various services and delegates, but now I need "Reactive-Cocoa -ise" so that I can work with the actual side of the interface.

However, in order to better understand this, I am writing a simple piece of code to try out the concepts. In this case, creating a wrapper for CLLocationManagerDelegate.

In the actual application, a usage example would be:

  • 1) When the application is loaded (viewDidLoad), then 2) Attempt to retrieve the location of the device on
  • 2.1) if location services are not included, then
  • 2.1.1) check the authorization status, and if allowed startMonitoringSignificantLocationChanges,
  • 2.1.2) else returns an error
  • 2.2) else (location services included)
  • 2.2.1) if the last location of the location manager was “last” (6 hours or less), return that
  • 2.2.2) else startMonitoringSignificantLocationChanges
  • 3) when returning the location (either immediately or through locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations), then we alsostopMonitoringSignificantLocationChanges
  • 4) If the code calling LocationManagerDelegate receives and causes an error, ask the delegate to specify a fixed default value
  • 5) Then the following code snippet uses the location (either extracted or default) to exit and make a bunch of calls to third-party services (calls to WebServices, etc.).

https://github.com/ippoippo/reactive-core-location-test

"" , . , , .

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];
}];

  • 1) ? catch, . , , ? defaultLocation, RACSignal, CLLocation??
  • 2) , sendNext sendCompleted? sendNext, , sendCompleted.
  • 3) , , . . - , . singleton, sendNext . , , latestLocationSignal, init?

(), , .

+4
3

? catch, .

. +[RACSignal return:] , :

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);
    return [RACSignal return:defaultLocation];
}];

, sendNext sendCompleted? sendNext, , sendCompleted.

, -sendNext:. , , -sendCompleted . , .

next (0 *), . . .

, , . . - , . singleton, sendNext . , , lastLocationSignal init?

, , , , ;) .

, , , . , . , .

+3

, ReactiveCocoa 3.0 :

import ReactiveCocoa
import LlamaKit

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: [AnyObject]!) {
        for item in locations {
            if let location = item as? CLLocation {
                sink.put(Event.Next(Box(location))
            }
        }
    }

}

, , :

var locationSignals : [CLLocation]  = []
signal.observe(next: { value in locationSignals.append(value)})

, pre-alpha , , , .

+2

ReactiveCocoa 4 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)
    }
}

:

 var locationSignals : [CLLocation]  = []  
 signal.observeNext({ newLocation in
      locationSignals.append(newLocation)
    })
+2

Source: https://habr.com/ru/post/1529357/


All Articles