Reputation: 71
I'm having a terrible time getting a UIAlertView to work within my custom NSObject class. In the research I've done it appears it should be possible but here's what I've run into.
First, here's my code:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSLog(@"clickedButtonAtIndex: %d", buttonIndex);
}
-(void)testAlertView {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"List Contains Items"
message:@"List contains items. Remove all items & delete?"
delegate:self
cancelButtonTitle:@"No"
otherButtonTitles:@"Yes", nil];
[alertView show];
}
If I set the delegate to self this code crashes as soon as I tap a button. If I set it to nil clickedButtonAtIndex is never called. I've tried with and without using the <UIAlertViewDelegate>
.
I know someone will ask 'why are you doing this in NSObject instead of in your UIViewController?'. Primarily because I want to separate this code out so I can use it from multiple places in my app. But also because this is a small piece of a larger block of logic that makes sense to be on it's own.
Any ideas what I'm doing wrong?
Thanks, Rich
Upvotes: 7
Views: 2436
Reputation: 2199
How To Present An Alert View Using UIAlertController When You Don't Have A View Controller. Detail description.
Yes, you can only use UIAlertController only in UIViewController classes. So how can we do it in NSObject classes. If you see the description link given above you will get to the answer. To summarise in a line for the above description: Create a new window above the the current window. This new window will be our viewController where we display alert. So using this viewController you can call the method [presentViewController: animated: completion:]
.
Answer:
dispatch_async(dispatch_get_main_queue(), ^{
UIWindow* window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
window.rootViewController = [UIViewController new];
window.windowLevel = UIWindowLevelAlert + 1;
NSString *msg=@“Your mssg";
UIAlertController* alertCtrl = [UIAlertController alertControllerWithTitle:@“Title" message:msg preferredStyle:UIAlertControllerStyleAlert];
[alertCtrl addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Yes",@"Generic confirm") style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
// do your stuff
// very important to hide the window afterwards.
window.hidden = YES;
}]];
UIAlertAction *cancelAction= [UIAlertAction actionWithTitle:@"cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
window.hidden = YES;
}];
[alertCtrl addAction:cancelAction];
//http://stackoverflow.com/questions/25260290/makekeywindow-vs-makekeyandvisible
[window makeKeyAndVisible]; //The makeKeyAndVisible message makes a window key, and moves it to be in front of any other windows on its level
[window.rootViewController presentViewController:alertCtrl animated:YES completion:nil];
});
Upvotes: 0
Reputation: 11
Add the NSObject as strong property:
#import "Logout.h" // is NSObject
.
.
.
@property (nonatomic, strong) Logout *logout;
Then you will get the delegatemethods called in your NSObject.
Don´t forget to register the delegate for the UIAlertView:
@interface Logout () <UIAlertViewDelegate>
and in your method:
UIAlertView *a = [[UIAlertView alloc] initWithTitle:@"title"
message:@"message" delegate:self cancelButtonTitle:@"cancel"
otherButtonTitles:@"ok", nil];
[a show];
Upvotes: 1
Reputation: 81
I had the same problem using ARC. The root of the problem was the same. I solved it by putting my custom NSObject into a "strong" property to make sure the object exists as long as the calling object (an UIVIewCOntroller in my case) exists, so when the delegate of my alert view is called I still have my custom object around and the delegate method works fine.
Upvotes: 8