我刚刚升级到 Xcode 4.5,以更新我的 iOS 应用程序以在 iPhone 5 的 4 英寸显示屏上运行,但我收到一条构建错误,线上显示
dismissModalViewControllerAnimated:' is deprecated
:
[self dismissModalViewControllerAnimated:NO];
我尝试使用完成处理程序(但设置为 NULL)更新为推荐的重载,如下所示:
[self dismissModalViewControllerAnimated:NO completion:NULL];
但是这一行抛出了两个错误:
warning: 'TabBarController' may not respond to '-presentModalViewController:animated:completion:'
Instance method '-presentModalViewController:animated:completion:' not found (return type defaults to 'id')
谢谢!
新方法是:
[self dismissViewControllerAnimated:NO completion:nil];
modal一词已被删除;正如当前 API 调用一样:
[self presentViewController:vc animated:NO completion:nil];
原因已在 2012 WWDC Session 236 - iOS 上视图控制器的演变 视频中进行了讨论。本质上,此 API 提供的视图控制器不再总是模态的,并且由于它们添加了完成处理程序,因此是重命名它的好时机。
回应马克的评论:
支持所有 4.3 及更高版本设备的最佳方式是什么?新的 该方法在 iOS4 中不起作用,但旧方法在 iOS6 中已弃用。
我意识到这几乎是一个单独的问题,但我认为值得一提,因为不是每个人都有钱每 3 年升级一次所有设备,所以我们很多人都有一些较旧的(5.0 之前)设备。尽管如此,尽管我说起来很痛苦,但你需要考虑是否值得将目标设置为低于 5.0。有许多新的、很酷的 API 在 5.0 以下不可用。苹果公司不断加大针对他们的难度。例如,armv6 支持从 Xcode 4.5 中删除。
要低于 5.0 的目标(只要完成块为零)只需使用方便的
respondsToSelector
: 方法。
if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){
[self presentViewController:test animated:YES completion:nil];
} else {
[self presentModalViewController:test animated:YES];
}
回应马克的另一条评论:
我的应用程序中可能有很多 If 语句!...我是 考虑创建一个封装此代码的类别, 在 UIViewControler 上创建类别让我被拒绝?
以及来自 Full Decent 的一张:
...有没有办法手动使其不显示编译器警告?
首先,不,在
UIViewController
上创建类别本身不会让您的应用程序被拒绝;除非该类别方法称为私有 API 或类似的东西。
类别方法是放置此类代码的绝佳位置。此外,由于只会调用一次已弃用的 API,因此只会出现一个编译器警告。
为了解决 Full Decent 的评论(问题),是的,您可以手动抑制编译器警告。 这是关于该主题的答案的链接。类别方法也是抑制编译器警告的好地方,因为您只在一处抑制警告。您当然不想随意地让编译器保持沉默。
如果我为此编写一个简单的类别方法,它可能是这样的:
@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
现在在 iOS 6 及以上版本中,您可以使用:
[[Picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
而不是:
[[Picker parentViewControl] dismissModalViewControllerAnimated:YES];
...您可以使用:
[self presentViewController:picker animated:YES completion:nil];
而不是
[self presentModalViewController:picker animated:YES];
[self dismissModalViewControllerAnimated:NO];
已被弃用。
请使用
[self dismissViewControllerAnimated:NO completion:nil];
来代替。
使用
[self dismissViewControllerAnimated:NO completion:nil];
警告仍然存在。为了摆脱它,我将它放入这样的选择器中:
if ([self respondsToSelector:@selector(dismissModalViewControllerAnimated:)]) {
[self performSelector:@selector(dismissModalViewControllerAnimated:) withObject:[NSNumber numberWithBool:YES]];
} else {
[self dismissViewControllerAnimated:YES completion:nil];
}
它对像我这样患有强迫症的人有益;)
这是我使用的相应的presentViewController版本,如果它可以帮助像我这样的其他新手:
if ([self respondsToSelector:@selector(presentModalViewController:animated:)]) {
[self performSelector:@selector(presentModalViewController:animated:) withObject:testView afterDelay:0];
} else {
[self presentViewController:configView animated:YES completion:nil];
}
[testView.testFrame setImage:info]; //this doesn't work for performSelector
[testView.testText setHidden:YES];
我“一般”使用了 ViewController,并且能够根据调用它执行的操作(使用 setHidden 和 setImage)使模态视图以不同的方式显示。之前一切都工作得很好,但是 PerformSelector 忽略了“设置”的东西,所以如果你像我一样尝试提高效率,那么最终这似乎是一个糟糕的解决方案......