如何修复“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
您需要设置sourceView
或barButtonItem
属性,否则它将崩溃并显示以下消息:
*** 由于未捕获的异常“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,如何改变它的大小呢?