dismissModalViewControllerAnimated已弃用


103

我刚刚升级到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')

谢谢!

Answers:


307

新方法是:

[self dismissViewControllerAnimated:NO completion:nil];

一词已被删除;与呈现API调用一样:

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

原因在2012年WWDC会议236-iOS视频上的视图控制器的演变中进行了讨论。本质上,此API提供的视图控制器不再总是模态的,并且由于它们添加了完成处理程序,因此现在是重命名它的好时机。

回应马克的评论:

支持所有4.3及更高版本设备的最佳方法是什么?新方法在iOS4中不起作用,但旧方法在iOS6中已弃用。

我意识到这几乎是一个单独的问题,但我认为值得一提,因为并非每个人都有钱每3年升级一次所有设备,因此我们许多人都拥有一些较旧的(5.0之前的)设备。尽管如此,我仍然难以置信,但您仍需要考虑是否值得在5.0以下定位。在5.0以下,有许多新的很酷的API不可用。苹果不断地将目标锁定在目标上。例如,armv6支持从Xcode 4.5中删除。

要定位到低于5.0的目标(只要完成块为零),请使用handy respondsToSelector:方法。

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

在回应Marc的另一条评论时:

我的应用程序中可能有很多If语句!...我正在考虑创建一个封装此代码的类别,是否会在UIViewControler上创建一个类别使我遭到拒绝?

还有一个来自《体面》:

...有没有办法手动导致不显示编译器警告?

首先,不,UIViewController在本身上创建类别不会使您的应用程序被拒绝;除非该类别方法称为私有API或类似的东西。

类别方法是此类代码的绝佳选择。而且,由于将仅对已弃用的API进行一次调用,因此将只有一个编译器警告。

要解决Full Decent的注释(问题),可以,您可以手动禁止编译器警告。这是有关该主题的SO答案的链接。类别方法也是抑制编译器警告的好地方,因为您只在一个地方抑制了警告。您当然不想四处闲逛使编译器静音。

如果要为此编写一个简单的类别方法,则可能是这样的:

@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

2
支持所有4.3及更高版本设备的最佳方法是什么?新方法在iOS4中不起作用,但旧方法在iOS6中已弃用。岩石和困难的地方?
Marc 2012年

@Marc我在回答中添加了您的关注点。
NJones 2012年

谢谢。在我的应用程序中可能有很多If语句!我猜想当使用'modalViewController'属性时,同样的方法也可以工作。我当时正在考虑创建一个封装此代码的类别,是否会在UIViewControler上创建类别被拒绝?
2012年

对于代码if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){ [self presentViewController:test animated:YES completion:nil]; } else { [self presentModalViewController:test animated:YES]; },有没有一种方法可以手动导致不显示编译器警告?
William Entriken

@FullDecent是的,可以。我用一些信息编辑了答案。
NJones

6

现在,在iOS 6及更高版本中,您可以使用:

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

代替:

[[Picker parentViewControl] dismissModalViewControllerAnimated:YES];

...您可以使用:

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

代替

[self presentModalViewController:picker animated:YES];    

4

[self dismissModalViewControllerAnimated:NO]; 已不推荐使用。

使用[self dismissViewControllerAnimated:NO completion:nil];代替。


4

[self dismissViewControllerAnimated:NO completion:nil];

3

警告仍然存在。为了摆脱它,我将其放入这样的选择器中:

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

它使像我这样的强迫症患者受益;)


您应该切换if语句,因为我认为不建议使用的方法不会导致respondsToSelector返回false。因此,dismissViewControllerAnimated:直到将来可能将它们dismissModalViewControllerAnimated:完全删除的更新之前,都不会调用新函数。
Jsdodgers

0

如果可以帮助像我这样的其他新手,这是我使用的相应的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忽略了“设置”的东西,因此,如果您像我一样尝试提高效率,最后似乎是一个糟糕的解决方案...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.