Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dismissModalViewControllerAnimated deprecated

Tags:

ios

ios6

I've just upgraded to XCode 4.5 to update my iOS app to run on the 4 inch display for the iPhone 5, but I'm getting a build error saying dismissModalViewControllerAnimated:' is deprecated on the line:

[self dismissModalViewControllerAnimated:NO];

I've tried updating to the recommended overload with a completion handler (but set to NULL) like this:

[self dismissModalViewControllerAnimated:NO completion:NULL];

But then this line throws two errors:

warning: 'TabBarController' may not respond to '-presentModalViewController:animated:completion:'
Instance method '-presentModalViewController:animated:completion:' not found (return type defaults to 'id')

Thanks!

like image 373
Mick Byrne Avatar asked Sep 16 '12 07:09

Mick Byrne


5 Answers

The new method is:

[self dismissViewControllerAnimated:NO completion:nil];

The word modal has been removed; As it has been for the presenting API call:

[self presentViewController:vc animated:NO completion:nil];

The reasons were discussed in the 2012 WWDC Session 236 - The Evolution of View Controllers on iOS Video. Essentially, view controllers presented by this API are no longer always modal, and since they were adding a completion handler it was a good time to rename it.

In response to comment from Marc:

What's the best way to support all devices 4.3 and above? The new method doesn't work in iOS4, yet the old method is deprecated in iOS6.

I realize that this is almost a separate question, but I think it's worth a mention since not everyone has the money to upgrade all their devices every 3 years so many of us have some older (pre 5.0) devices. Still, as much as it pains me to say it, you need to consider if it is worth targeting below 5.0. There are many new and cool APIs not available below 5.0. And Apple is continually making it harder to target them; armv6 support is dropped from Xcode 4.5, for example.

To target below 5.0 (as long as the completion block is nil) just use the handy respondsToSelector: method.

if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){
    [self presentViewController:test animated:YES completion:nil];
} else {
    [self presentModalViewController:test animated:YES];
}

In response to another comment from Marc:

That could be quite a lot of If statements in my application!...I was thinking of creating a category that encapsulated this code, would creating a category on UIViewControler get me rejected?

and one from Full Decent:

...is there a way to manually cause that to not present a compiler warning?

Firstly, no, creating a category on UIViewController in and of itself will not get your app rejected; unless that category method called private APIs or something similar.

A category method is an exceedingly good place for such code. Also, since there would be only one call to the deprecated API, there would be only one compiler warning.

To address Full Decent's comment(question), yes you can suppress compiler warnings manually. Here is a link to an answer on SO on that very subject. A category method is also a great place to suppress a compiler warning, since you're only suppressing the warning in one place. You certainly don't want to go around silencing the compiler willy-nilly.

If I was to write a simple category method for this it might be something like this:

@implementation UIViewController (NJ_ModalPresentation)
-(void)nj_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion{
    NSAssert(completion == nil, @"You called %@ with a non-nil completion. Don't do that!",NSStringFromSelector(_cmd));
    if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){
        [self presentViewController:viewControllerToPresent animated:flag completion:completion];
    } else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        [self presentModalViewController:viewControllerToPresent animated:flag];
#pragma clang diagnostic pop
    }
}
@end
like image 148
NJones Avatar answered Nov 15 '22 11:11

NJones


Now in iOS 6 and above, you can use:

[[Picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];

Instead of:

[[Picker parentViewControl] dismissModalViewControllerAnimated:YES];

...And you can use:

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

Instead of

[self presentModalViewController:picker animated:YES];    
like image 6
Dipang Avatar answered Nov 15 '22 12:11

Dipang


[self dismissModalViewControllerAnimated:NO]; has been deprecated.

Use [self dismissViewControllerAnimated:NO completion:nil]; instead.

like image 4
Jayprakash Dubey Avatar answered Nov 15 '22 10:11

Jayprakash Dubey


Use

[self dismissViewControllerAnimated:NO completion:nil];
like image 4
Mak083 Avatar answered Nov 15 '22 12:11

Mak083


The warning is still there. In order to get rid of it I put it into a selector like this:

if ([self respondsToSelector:@selector(dismissModalViewControllerAnimated:)]) {
    [self performSelector:@selector(dismissModalViewControllerAnimated:) withObject:[NSNumber numberWithBool:YES]];
} else {
    [self dismissViewControllerAnimated:YES completion:nil];
}

It benefits people with OCD like myself ;)

like image 3
kjoelbro Avatar answered Nov 15 '22 11:11

kjoelbro