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!
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
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];
[self dismissModalViewControllerAnimated:NO];
has been deprecated.
Use [self dismissViewControllerAnimated:NO completion:nil];
instead.
Use
[self dismissViewControllerAnimated:NO completion:nil];
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 ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With