Reputation: 501
Is there a way to programmatically dismiss dialogs like the ones where the app wants to access photos, access contacts and access location?
I think there's a way by swizzling API methods, but I don't really know which. What is the methodology to find out which methods need to be swizzled? If swizzling is not the way then what could be another alternative?
As a note, this is not for a product, is just for testing so swizzling is a good option if it works.
Upvotes: 2
Views: 955
Reputation: 501
Type this code in your UIApplicationDelegate
implementation (importing <AddressBook/AddressBook.h>
is necessary:
ABAuthorizationStatus ABAddressBookGetAuthorizationStatus(void) {
return kABAuthorizationStatusAuthorized;
}
Type in the following method in your UIApplicationDelegate
implementation, or wherever you need it, a helper class would be best. (importing <objc/runtime.h>
is required:
- (void)swizzleSelector:(SEL)selector fromInstancesOfClass:(Class)clazz withBlock:(id)block {
id replaceBlock = Block_copy(block);
Method origMethod = class_getInstanceMethod(clazz, selector);
IMP origImpl = method_getImplementation(origMethod);
IMP replaceImpl = imp_implementationWithBlock(replaceBlock);
method_setImplementation(origMethod, replaceImpl);
}
- (void)swizzleSelector:(SEL)selector fromClass:(Class)clazz withBlock:(id)block {
id replaceBlock = Block_copy(block);
Method origMethod = class_getClassMethod(clazz, selector);
IMP origImpl = method_getImplementation(origMethod);
IMP replaceImpl = imp_implementationWithBlock(replaceBlock);
method_setImplementation(origMethod, replaceImpl);
}
Do the following in your UIApplicationDelegate
implementation. (importing <CoreLocation/CoreLocation.h>
is required):
[self swizzleSelector:@selector(startUpdatingLocation) fromInstancesOfClass:[CLLocationManager class] withBlock:^{}];
[self swizzleSelector:@selector(startMonitoringSignificantLocationChanges) fromInstancesOfClass:[CLLocationManager class] withBlock:^{}];
[self swizzleSelector:@selector(locationServicesEnabled) fromClass:[CLLocationManager class] withBlock:^{ return NO; }];
Do the following in your UIApplicationDelegate
implementation. (importing <AssetsLibrary/AssetsLibrary.h>
is required):
[self swizzleSelector:@selector(authorizationStatus) fromClass:[ALAssetsLibrary class] withBlock:^{ return ALAuthorizationStatusAuthorized; }];
[self swizzleSelector:@selector(enumerateGroupsWithTypes:usingBlock:failureBlock:) fromInstancesOfClass:[ALAssetsLibrary class] withBlock:^{}];
Upvotes: 1
Reputation: 23634
You should be able to access an alert from anywhere in your app like this. This works for regular alerts but I have not tried it with system alerts (It is possible they don't sit in the same hierarchy as regular alerts, in which case you can't get to them at all). If it does work and you try to release an app with this, it will almost certainly get rejected.
for (UIWindow* w in [UIApplication sharedApplication].windows)
{
for (NSObject* o in w.subviews)
if ([o isKindOfClass:[UIAlertView class]])
{
// as an example, this will just dismiss/cancel the alert
[(UIAlertView*)o dismissWithClickedButtonIndex:[(UIAlertView*)o cancelButtonIndex] animated:YES];
}
}
Upvotes: 0