如何修复“UIPopoverController 已弃用”警告?

Posted

技术标签:

【中文标题】如何修复“UIPopoverController 已弃用”警告?【英文标题】:How can I fix the "UIPopoverController is deprecated" warning? 【发布时间】:2015-09-28 08:05:15 【问题描述】:

我正在使用此代码:

mediaLibraryPopover = [[UIPopoverController alloc] 
                        initWithContentViewController:avc];
[self.mediaLibraryPopover presentPopoverFromRect:[theButton bounds] 
                          inView:theButton 
                          permittedArrowDirections:UIPopoverArrowDirectionAny 
                          animated:YES];

我在 Xcode 7 中收到此警告:

UIPopoverController 已弃用,首先在 ios 9.0 中弃用 - UIPopoverController 已弃用。弹出框现在实现为 UIViewController 演示文稿。使用 UIModalPresentationPopover 和 UIPopoverPresentationController 的模态展示风格。

【问题讨论】:

UIStorybaordPopoverSegue.h 中的弃用警告得到了改进,现在提供了方向:“Access destinationViewController.popoverPresentationController from your segue's performHandler...” 【参考方案1】:

您不再需要UIPopoverController 来呈现视图控制器。 相反,您可以将视图控制器的modalPresentationStyle 设置为UIModalPresentationPopover

您可以使用以下代码:

avc.modalPresentationStyle = UIModalPresentationPopover;
avc.popoverPresentationController.sourceView = theButton;
[self presentViewController:avc animated:YES completion:nil];

UIModalPresentationPopover

在水平规则的环境中,一个 内容显示在弹出视图中的演示样式。 背景内容变暗并在弹出框之外点击 要关闭的弹出框。如果您不希望点击关闭 popover,你可以为 passthroughViews 分配一个或多个视图 关联的 UIPopoverPresentationController 对象的属性, 您可以从 popoverPresentationController 属性中获取。

在水平紧凑的环境中,此选项的行为与 UIModalPresentationFullScreen。

适用于 iOS 8.0 及更高版本。

参考UIModalPresentationStyle Reference


您需要设置sourceViewbarButtonItem 属性,否则它将崩溃并显示以下消息:

*** 由于未捕获的异常“NSGenericException”而终止应用程序,原因:“UIPopoverPresentationController (***) 应该有一个非零 在演示发生之前设置的 sourceView 或 barButtonItem。'

为了正确锚定弹出箭头,您还需要指定sourceRect 属性。

avc.modalPresentationStyle                   = UIModalPresentationPopover;
avc.popoverPresentationController.sourceView = self.view;
avc.popoverPresentationController.sourceRect = theButton.frame;
[self presentViewController:avc animated:YES completion:nil];

请参阅sourceView 和sourceRect 了解更多详情。

【讨论】:

我发现我需要更改 avc.popoverPresentationController.sourceView = self.view; 并添加 avc.popoverPresentationController.sourceRect = theButton.frame; 才能正确定位弹出框。 @mark 有一个好点,但我认为您不需要更改 sourceView。当我这样做时,我按原样离开了avc.popoverPresentationController.sourceView = theButton;,并简单地添加了avc.popoverPresentationController.sourceRect = theButton.bounds; 如何以这种方式关闭 UIModalPresentationPopover .?正常的dismissviewcontroller .? @mark 如果它是从 presentPopoverFromBarButtonItem 呈现的:替换是什么。? @Anz:你需要设置popoverpresentationcontroller的permittedArrowDirections属性【参考方案2】:

Apple 有官方的方式来呈现和配置 iOS8 的弹出框:https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIPopoverPresentationController_class/index.html

虽然类似于@MidhunMP 的回答,但值得注意的是以下段落:

调用后配置弹出框展示控制器 presentViewController:animated:completion: 可能看起来 违反直觉,但 UIKit 不会创建演示控制器 直到您开始演示。另外,UIKit 必须等待 直到下一个更新周期才能在屏幕上显示新内容。 该延迟使您有时间配置演示控制器 你的弹出窗口。

如果您愿意,也可以通过委托 (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIPopoverPresentationControllerDelegate_protocol/index.html) 来配置和响应事件。

一个例子,搁置委托的使用:

// Present the controller using the popover style.
controller.modalPresentationStyle = UIModalPresentationPopover;
[self presentViewController:controller animated:YES completion:nil];

// Popover presentation controller was created when presenting; now  configure it.
UIPopoverPresentationController *presentationController =
        [controller popoverPresentationController];
presentationController.permittedArrowDirections = UIPopoverArrowDirectionLeft;
presentationController.sourceView = containerFrameOfReferenceView;
// arrow points out of the rect specified here
presentationController.sourceRect = childOfContainerView.frame;

但你也想忽略这个。要在不使用委托的情况下执行此操作,您的呈现控制器只需调用:

[self dismissViewControllerAnimated:YES completion:nil];

但是如果我旋转我的设备,并且弹出框没有指向正确的区域怎么办?您的演示控制器可以处理它:

// Respond to rotations or split screen changes
- (void)viewWillTransitionToSize:(CGSize)size
       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator 
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    [coordinator animateAlongsideTransition:nil 
                                 completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) 
        // Fix up popover placement if necessary, after the transition.
        if (self.presentedViewController) 
            UIPopoverPresentationController *presentationController =
                    [self.presentedViewController popoverPresentationController];
            presentationController.sourceView = containerFrameOfReferenceView;
            presentationController.sourceRect = childOfContainerView.frame;
        
    ];

【讨论】:

【参考方案3】:

如果想要直接从 Button Action 那么这个代码可以使用

SecondViewController *destinationViewController = (SecondViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"second"];
destinationViewController.modalPresentationStyle = UIModalPresentationPopover;
destinationViewController.popoverPresentationController.sourceView = self.customButton;

// Set the correct sourceRect given the sender's bounds
destinationViewController.popoverPresentationController.sourceRect = ((UIView *)sender).bounds;
[self presentViewController:destinationViewController animated:YES completion:nil];

【讨论】:

【参考方案4】:

编辑:关于否决票。首先是一个有趣且相关的故事:

http://www.folklore.org/StoryView.py?story=Negative_2000_Lines_Of_Code.txt

我在下面发布了答案,以帮助那些可能被困在 iPad/iPhone 在呈现媒体选择器 UI 时仍需要单独执行路径的思维方式的编码人员。发布这在其他答案中并不清楚。此解决方案路径简化了我的代码和我的应用程序的未来维护。我认为其他人可能会发现这种观点很有用,因为有时删除正确的代码行可能是一个很好的解决方案。

编辑结束。

如果您已经有一个工作程序并且只是想摆脱折旧警告,这可能对您有用。

在我的代码和我的理解中,弹出框是为 iPad 引入的,并且是特定于 iPad 的。苹果似乎改变了这一点。所以,如果你已经有一个使用类似这样的工作程序:

if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
    // use popovers 
else
    //  don't use popovers

您可以做的只是摆脱 iPad 特定的代码(这可能是使用 Popovers 的代码)并让您的程序在 iPhone 和 iPad 上运行相同的指令。这对我有用。

【讨论】:

答案没用:不言而喻,删除导致您不想要的警告的代码,将删除警告。 但是,您不再需要特殊代码来处理 iPad 上的图像选择器,这就是我试图提出的观点。 此外,您的回答暗示删除代码仍会在 iPad 上提供弹出框功能,但事实并非如此。它只是完全放弃了对弹出框的支持,这是一个重要的 iPad UI 功能。 在我的情况下,这个答案很有帮助:XCode 在创建空应用程序时从模板中插入了 PopoverController 代码。我从未打算直接支持 iPad - 但我忘了删除这个未使用的代码。到目前为止,它会引发“已弃用”警告 => 支持 +1

以上是关于如何修复“UIPopoverController 已弃用”警告?的主要内容,如果未能解决你的问题,请参考以下文章

UIPopoverController:如何移动它?

如何在 UIPopoverController 上创建按钮 [关闭]

如何观察 UIPopoverController 何时被解雇?

UIPopoverController,如何改变它的大小呢?

如何删除 UIPopoverController 中的“模糊”阴影

如何使 UIPopoverController 自动改变其箭头方向