-->

How to use MKLocationManager (a Private API) in iO

2019-03-21 16:11发布

问题:

I need to call

[[MKLocationManager sharedLocationManager] _applyChinaLocationShift:newLocation]

in my iOS app.

I believe MKLocationManager is a private class, and there does not seem to have a MapKit/MKLocationManager.h file.

I'm not targeting App Store. It's there any way I can use that private API?

Update at 2011-6-23

I really need the answer, or could I de-complie the iOS SDK?

100 reputation is almost all I have. Please help me.

回答1:

If the above answer isn't working for you, this may be because the entire class is private (including it's header). Here's an alternative approach using some runtime trickery; you must be sure that the signature is correct but we can use some defensive coding to avoid a crash.

First, unless you are calling this just once, I'd wrap up the code in a helper method:

// in some header file, you may want to give the method a prefix too
CLLocation *ApplyLocationManagerChinaLocationShift(CLLocation *newLocation);

You can now use NSClassFromString to obtain a reference to the class and performSelector to perform the method. We can try and make sure the method exists first to be on the safe side:

CLLocation *ApplyLocationManagerChinaLocationShift(CLLocation *newLocation)
{
  id sharedLocationManager = [NSClassFromString(@"MKLocationManager") performSelector:@selector(sharedLocationManager)];

  SEL theSelector = @selector(_applyChinaLocationShift:);

  // this will ensure sharedLocationManager is non-nil and responds appropriately
  if (![sharedLocationManager respondsToSelector:theSelector]) {
    return nil; // fail silently - check this in the caller
  }
  return [sharedLocationManager performSelector:theSelector withObject:newLocation];
}

I haven't run the above code but it should do the trick. If for some reason the @selector() calls do not work (I think they should), then you can replace them with NSSelectorFromString() calls instead.



回答2:

You can simply create the method description yourself, essentially creating your own category on MKLocationManager. By defining how the private method looks you make it callable. But you must be certain about it's signature, because if you are off then your app will just crash.

This category could be put in it's own .h file or if you only use it in one place right above the @implementation.

@interface MKLocationManager (china)
- (CLLocation *)_applyChinaLocationShift:(CLLocation *)newLocation;
@end