Reputation: 4350
I want to dismiss my UIAlertController with a click on the 'Cancel' button when my app goes in to background.
I've set up the background notification with
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
Then in my appDidEnterBackground function I have:
- (void)appDidEnterBackground {
if (_alertController) {
UIAlertAction *cancelAction = [[_alertController actions] objectAtIndex:0];
//HERE: is there a way to trigger the cancelAction??
[_alertController dismissViewControllerAnimated:NO completion:nil];
}
}
What I'm struggling with is how to trigger the UIAlertAction programmatically. Is this possible?
Upvotes: 4
Views: 5594
Reputation: 11
This is old but it is the top result when looking for how to trigger a UIAlertAction programmatically.
Just in case anyone (still doing objC) is prepared to use internal methods - this works with iOS 10 and 11:
- (void)triggerAction:(UIAlertAction*)action onAlertController:(UIAlertController*)alert {
SEL triggerSelector = NSSelectorFromString(@"_dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:");
NSMethodSignature* signature = [[alert class] instanceMethodSignatureForSelector:triggerSelector];
if (!signature) {
// Try pre iOS11 - OK as we're not trying to use the completion block
triggerSelector = NSSelectorFromString(@"_dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:");
signature = [[alert class] instanceMethodSignatureForSelector:triggerSelector];
}
NSAssert(signature != nil, @"Couldn't find trigger method");
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:alert];
[invocation setSelector:triggerSelector];
BOOL boolValue = YES; // Animated & dimmingView
[invocation setArgument:&boolValue atIndex:2];
[invocation setArgument:&action atIndex:3];
[invocation setArgument:&boolValue atIndex:4];
// Not setting anything for the dismissCompletion block atIndex:5
[invocation invoke];
}
Upvotes: 0
Reputation: 4350
I answered this with using the suggestion made by MCKapur.
I already had the UIAlertController in a singleton. What I did was define a variable in my singleton to save the completion action:
@property (copy, nonatomic) void (^completion)(BOOL);
Then when I set up the UIAlertController to show it, I also setup the completion code with:
_completion = ^(BOOL cancelled) {
if (block) {
block (NO, nil);
}
};
Finally, I changed the appDidEnterBackground call to:
- (void)appDidEnterBackground {
if (_alertController) {
if (_completion) {
_completion(NO);
_completion = nil;
}
[_alertController dismissViewControllerAnimated:NO completion:nil];
}
}
Upvotes: 4