3

I've got a class method that wants to use CLLocationManager and some of its delegate methods.

What is the best way to access the delegate methods from the class method, since I don't have a true instance level "self"? I could instantiate a self and use as the delegate, which would let the delegate methods run, but doesn't show how to get the data out. What's the best approach?

// desired end function, which runs a block when location is found
[SFGeoPoint geoPointForCurrentLocationInBackground:^(SFGeoPoint *geoPoint, NSError *error) {
    if (!error) {
        // do something with the new geoPoint
        NSLog(@"GeoPoint: %@", geoPoint);
    }
}];


// SFGeoPoint class, key points
static CLLocationManager *_locationManager = nil;

// get geo point for current location and call block with it
+ (void) geoPointForCurrentLocationInBackground:( void ( ^ )( SFGeoPoint*, NSError* ) ) locationFound {

    SFGeoPoint *point = [[SFGeoPoint alloc] init];

    _locationManager = [[CLLocationManager alloc] init];

    // ?????????
    _locationManager.delegate = self;  // this gives a warning about incompatible pointer type assigning Delegate from Class; 
    _locationManager.delegate = point;  // could work, but how to get feedback?  

    _locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
    _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [_locationManager startUpdatingLocation];

    [_locationManager startUpdatingLocation];
    locationFound(point, nil);
}


/////////// Core Location Delegate
+ (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
       fromLocation:(CLLocation *)oldLocation {

    [_locationManager stopUpdatingLocation];

    if (_locationBlock) {
        _locationBlock(newLocation);
    }
}
3
  • "this doesn't work" What "doesn't work" about it? Commented Mar 27, 2014 at 4:30
  • In the class method, I can't assign "self" to the delegate without getting a Warning about incompatible pointer type assigning Delegate from Class. It is a good point that it isn't an Error though, and can be made to work I'm realizing. I prefer the layout of the below solution though, as I can still access instance variables defined in the class, instead of needing static variables. Commented Mar 27, 2014 at 15:54
  • it's a warning because the class object does not nominally implement the protocol. You can get rid of the warning by casting to id: = (id)self. Conceptually the two are not that much different, just that in this case you are using the class object itself as a delegate instead of some instance, saving you the need to create another object. Commented Mar 27, 2014 at 18:09

1 Answer 1

13
+50

I would rework what you're doing and not use class methods. Instead, use a shared instance singleton, which will allow you to write your code almost identically but gives you an instance to work with and therefore store variables and assign delegates.

Just in case you are unfamiliar with the syntax:

+ (instancetype) shared
{
    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

Then just change all of your + (class) methods to be - (instance) methods and access your class with [[MyClass shared] doWhatever];

edit with optional wrapper:

If you really wanna call the method without an instance you can write a wrapper that would do something like this:

+ (void) doWhatever
{
    [[self shared] doWhatever];
}

That said I would generally not recommend doing this because you are not saving much code and adding possible confusion in the future as to what kind of method this actually is from the caller's perspective.

Sign up to request clarification or add additional context in comments.

4 Comments

This does get [[SFGeoPoint instance] geoPoint...], but still hoping to get the simpler [SFGeoPoint getPoint...] going.
I edited my answer to add a way to do what you're asking, by just adding a class wrapping method around the instance method. This is as simple as this will get and is most likely the best solution.
Amazingly simple final point, and the singleton works well too.
This answer was very helpful, gave extra reward.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.