Created
June 1, 2013 03:57
-
-
Save ericallam/5689235 to your computer and use it in GitHub Desktop.
Mocking out CLLocationManager
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <CoreLocation/CoreLocation.h> | |
extern CLLocationDegrees kMockedLatitude; | |
extern CLLocationDegrees kMockedLongitude; | |
@interface CLLocationManager (MockingLocation) | |
+ (BOOL)custom_locationServicesEnabled; | |
+ (CLAuthorizationStatus)custom_authorizationStatus; | |
-(void)custom_startUpdatingLocation; | |
-(CLLocation *)custom_location; | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "CLLocationManager+MockingLocation.h" | |
// The lat and long of the mocked current location | |
CLLocationDegrees kMockedLatitude = 28.5388; | |
CLLocationDegrees kMockedLongitude = -81.3756; | |
// This category implements methods that will be swizzled to replace key methods | |
// in CLLocationManager to mock out the user location | |
@implementation CLLocationManager (MockingLocation) | |
// replaces locationServicesEnabled; | |
+ (BOOL)custom_locationServicesEnabled; | |
{ | |
return YES; | |
} | |
// replaces startUpdatingLocation, will send the locationManager:didUpdateLocations: message | |
// to the delegate after a wait of 0.1 seconds using dispatch_after to simulate how | |
// startUpdatingLocation actually works. This will not simulate any kind of location errors | |
-(void)custom_startUpdatingLocation; | |
{ | |
CLLocation *usersCurrentLocation = [[CLLocation alloc] initWithLatitude:kMockedLatitude longitude:kMockedLongitude]; | |
if (self.delegate) { | |
if ([self.delegate respondsToSelector:@selector(locationManager:didUpdateLocations:)]) { | |
// Send the locationManager:didUpdateLocations: message to location manager after 0.1 seconds | |
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ | |
NSArray *locations = @[usersCurrentLocation]; | |
[self.delegate locationManager:self didUpdateLocations:locations]; | |
}); | |
} | |
} | |
} | |
// replaces location, returns the mocked CLLocation object, does not current | |
// have any support for mocking altitude or anything other than lat/long | |
-(CLLocation *)custom_location; | |
{ | |
return [[CLLocation alloc] initWithLatitude:kMockedLatitude longitude:kMockedLongitude]; | |
} | |
@end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
@interface CSSwizzler : NSObject | |
+(void)swizzleClass:(id)cls | |
replaceClassMethod:(SEL)origMethodSelector | |
withMethod:(SEL)replacementMethodSelector; | |
+(void)swizzleClass:(id)cls | |
replaceMethod:(SEL)origMethodSelector | |
withMethod:(SEL)replacementMethodSelector; | |
+(void)swizzleClassOfInstance:(id)inst | |
replaceMethod:(SEL)origMethodSelector | |
withMethod:(SEL)replacementMethodSelector; | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "CSSwizzler.h" | |
#import <objc/message.h> | |
#import <objc/runtime.h> | |
@implementation CSSwizzler | |
+(void)swizzleClass:(id)cls | |
replaceClassMethod:(SEL)origMethodSelector | |
withMethod:(SEL)replacementMethodSelector; | |
{ | |
Method origMethod = nil, altMethod = nil; | |
origMethod = class_getClassMethod(cls, origMethodSelector); | |
altMethod = class_getClassMethod(cls, replacementMethodSelector); | |
method_exchangeImplementations(origMethod, altMethod); | |
} | |
+(void)swizzleClass:(id)cls | |
replaceMethod:(SEL)origMethodSelector | |
withMethod:(SEL)replacementMethodSelector; | |
{ | |
Method origMethod = nil, altMethod = nil; | |
origMethod = class_getInstanceMethod(cls, origMethodSelector); | |
altMethod = class_getInstanceMethod(cls, replacementMethodSelector); | |
method_exchangeImplementations(origMethod, altMethod); | |
} | |
+(void)swizzleClassOfInstance:(id)inst | |
replaceMethod:(SEL)origMethodSelector | |
withMethod:(SEL)replacementMethodSelector; | |
{ | |
const char *str = [[[inst class] description] UTF8String]; | |
Class cls = objc_getClass(str); | |
Method origMethod = nil, altMethod = nil; | |
origMethod = class_getInstanceMethod(cls, origMethodSelector); | |
altMethod = class_getInstanceMethod(cls, replacementMethodSelector); | |
method_exchangeImplementations(origMethod, altMethod); | |
} | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "LocationMocker.h" | |
#import "CSSwizzler.h" | |
#import "CLLocationManager+MockingLocation.h" | |
@implementation LocationMocker | |
// This method gets automatically called as soon as this class | |
// is loaded | |
+(void) load; | |
{ | |
// locationServicesEnabled exists as both a class method | |
[CSSwizzler swizzleClass:[CLLocationManager class] | |
replaceClassMethod:@selector(locationServicesEnabled) | |
withMethod:@selector(custom_locationServicesEnabled)]; | |
// and an instance method on CLLocationManager, thus we will swizzle it | |
// twice | |
[CSSwizzler swizzleClass:[CLLocationManager class] | |
replaceMethod:@selector(locationServicesEnabled) | |
withMethod:@selector(custom_locationServicesEnabled)]; | |
[CSSwizzler swizzleClass:[CLLocationManager class] | |
replaceMethod:@selector(startUpdatingLocation) | |
withMethod:@selector(custom_startUpdatingLocation)]; | |
[CSSwizzler swizzleClass:[CLLocationManager class] | |
replaceMethod:@selector(location) | |
withMethod:@selector(custom_location)]; | |
} | |
@end |
Hey @rallo, there is no need for a header as it is not imported anyhow.
You would add the following somewhere either in the .m or .h
@interface LocationMocker: NSObject
@end
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is there a LocationMocker.h file missing? I see you import it in the LocationMocker.m