lizzy91 lizzy91 - 5 months ago 95
iOS Question

How do I add a UIAlertController in app delegate (obj-c)

This is the code I was using prior to UIAlertView being deprecated:

//OLD UIALERTVIEW
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

// check to see if newer version exists to alert the user
BOOL updateAvailable = NO;
NSDictionary *updateDictionary = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:@"PLIST_URL_HERE"]];
NSArray *items = [updateDictionary objectForKey:@"items"];
NSDictionary *itemDict = [items lastObject];
NSDictionary *metaData = [itemDict objectForKey:@"metadata"];
NSString *newversion = [metaData valueForKey:@"bundle-version"];
NSString *currentversion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];

//updateAvailable = [newversion compare:currentversion options:NSNumericSearch] == NSOrderedDescending; //default code
updateAvailable = [@"1.3" compare:currentversion options:NSNumericSearch] == NSOrderedDescending; //force update
//updateAvailable = [@"1.1" compare:currentversion options:NSNumericSearch] == NSOrderedDescending; //force no update

if (updateAvailable) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"UPDATE AVAILABLE" message:@"Click OK to update the application to the latest version" delegate:self cancelButtonTitle:@"Later" otherButtonTitles:@"OK", nil];
[alert show];
}
}


-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex != [alertView cancelButtonIndex]) {
// point to the pList on dropbox to install the
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"PLIST_URL_HERE"]];
exit(0);


I am trying to update it to use UIAlertController instead.
heres the code I'm using for that

//NEW UIACTIONCONTROLLER
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

// check to see if newer version exists to alert the user
BOOL updateAvailable = NO;
NSDictionary *updateDictionary = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:@"PLIST_URL_HERE"]];
NSArray *items = [updateDictionary objectForKey:@"items"];
NSDictionary *itemDict = [items lastObject];
NSDictionary *metaData = [itemDict objectForKey:@"metadata"];
NSString *newversion = [metaData valueForKey:@"bundle-version"];
NSString *currentversion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];

//updateAvailable = [newversion compare:currentversion options:NSNumericSearch] == NSOrderedDescending; //default code
updateAvailable = [@"1.3" compare:currentversion options:NSNumericSearch] == NSOrderedDescending; //force update
//updateAvailable = [@"1.1" compare:currentversion options:NSNumericSearch] == NSOrderedDescending; //force no update

if (updateAvailable) {
UIAlertController * alert= [UIAlertController alertControllerWithTitle:@"UPDATE AVAILABLE" message:@"Click OK to update the application to the latest version" preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"PLIST_URL_HERE"]];
exit(0);
}];

UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];

[alert addAction:ok];
[alert addAction:cancel];

[self presentViewController:alert animated:YES completion:nil];
}
}


problem is this code:


[self presentViewController:alert animated:YES completion:nil];


gives me this error:


/Users/liz/Desktop/CactusQueuesGit/CactusQueue/AppDelegate.m:154:15: No visible @interface for 'AppDelegate' declares the selector 'presentViewController:animated:completion:'


I can put that code in
viewDidLoad
but I don't want the alert popping up every time the users go to the TableView. I just want it to load ONLY when the app is opened.

how do I go about doing this?

Answer

Per Apple Documentation, UIAlertCobtroller is just like another view controller which needs a view controller as base to present on.

To present an UIAlertCobtroller from AppDelegate, you can create a temporary window with an empty view controller in it and present on top of it. Something like this:

self.alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.alertWindow.rootViewController = [[UIViewController alloc] init];
self.alertWindow.windowLevel = UIWindowLevelAlert + 1;
[self.alertWindow makeKeyAndVisible];
[self.alertWindow.rootViewController presentViewController:alertControl animated:YES completion:nil];

This window will automatically be taken out of memory once alert is dismissed.

You can also present your alert on rootViewController if it has been initialized and is added in view hierarchy.

I hope you got why you are getting this error now. Technically, AppDelegate is not a view controller and so does not respond to presentViewController:animated:completion: method.

Comments