【问题标题】:dismissModalViewControllerAnimated deprecated不推荐使用dismissModalViewControllerAnimated
【发布时间】:2012-09-16 07:38:26
【问题描述】:

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

谢谢!

【问题讨论】:

    标签: ios ios6


    【解决方案1】:

    新方法是:

    [self dismissViewControllerAnimated:NO completion:nil];
    

    modal这个词已被删除;就像呈现的 API 调用一样:

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

    2012 WWDC Session 236 - iOS 上视图控制器的演变视频中讨论了原因。从本质上讲,这个 API 提供的视图控制器不再总是模态的,因为它们添加了一个完成处理程序,所以现在是重命名它的好时机。

    回应 Marc 的评论:

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

    我意识到这几乎是一个单独的问题,但我认为值得一提,因为不是每个人都有钱每 3 年升级一次所有设备,所以我们中的许多人都有一些旧的(5.0 之前的)设备。尽管如此,尽管我说起来很痛苦,但您需要考虑是否值得将其定位在 5.0 以下。在 5.0 以下,有许多新的很酷的 API 不可用。 Apple 不断加大针对他们的难度;例如,从 Xcode 4.5 中删除了 armv6 支持。

    要低于 5.0(只要完成块为 nil),只需使用方便的 respondsToSelector: 方法。

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

    回应 Marc 的另一条评论:

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

    还有一个来自 Full Decent:

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

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

    类别方法对于此类代码来说是一个非常好的地方。此外,由于只有一次对已弃用 API 的调用,因此只会出现一次编译器警告。

    要解决 Full Decent 的评论(问题),是的,您可以手动禁止编译器警告。 Here is a link to an answer on SO on that very subject。类别方法也是抑制编译器警告的好地方,因为您只在一个地方抑制警告。您当然不想无所事事地使编译器静音。

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

    @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
    

    【讨论】:

    • 支持所有设备 4.3 及更高版本的最佳方式是什么?新方法在 iOS4 中不起作用,但旧方法在 iOS6 中已弃用。摇滚和坚硬的地方?
    • @Marc 我已添加到我的答案中以解决您的问题。
    • 谢谢。在我的应用程序中,这可能是相当多的 If 语句!我猜想在使用 'modalViewController' 属性时,同样的方法也可以工作。我正在考虑创建一个封装此代码的类别,在 UIViewControler 上创建一个类别会让我被拒绝吗?
    • 对于代码if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){ [self presentViewController:test animated:YES completion:nil]; } else { [self presentModalViewController:test animated:YES]; },有没有办法手动使其不显示编译器警告?
    • @FullDecent 是的,你可以。我用一些相关信息编辑了我的答案。
    【解决方案2】:

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

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

    代替:

    [[Picker parentViewControl] dismissModalViewControllerAnimated:YES];
    

    ...你可以使用:

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

    代替

    [self presentModalViewController:picker animated:YES];    
    

    【讨论】:

      【解决方案3】:

      [self dismissModalViewControllerAnimated:NO]; 已被弃用。

      请改用[self dismissViewControllerAnimated:NO completion:nil];

      【讨论】:

        【解决方案4】:

        使用

        [self dismissViewControllerAnimated:NO completion:nil];
        

        【讨论】:

          【解决方案5】:

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

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

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

          【讨论】:

          • 您应该切换 if 语句,因为我相信已弃用的方法不会导致 respondsToSelector 返回 false。因此,新的 dismissViewControllerAnimated: 将永远不会被调用,直到未来的更新可能会完全删除 dismissModalViewControllerAnimated:
          【解决方案6】:

          这是我使用的相应的 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 忽略了“设置”的东西,所以如果你想像我一样努力提高效率,这似乎是一个糟糕的解决方案......

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-04-22
            • 2012-11-14
            • 2019-11-08
            • 2019-11-08
            • 2020-01-03
            • 2011-12-02
            • 2015-01-24
            相关资源
            最近更新 更多