iOS-如何解决“已弃用UIPopoverController”警告?

我正在使用此代码:

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的模式表示样式。

4个解决方案
113 votes

您不再需要sourceView来提供视图控制器。相反,您可以将视图控制器的barButtonItem设置为UIModalPresentationPopover

您可以为此使用以下代码:

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

UIModalPresentationPopover

在水平规则的环境中,   在弹出窗口中显示内容的演示样式。   背景内容变暗,并在弹出原因之外点击   弹出窗口将被撤消。 如果不想让水龙头关闭   弹出框,您可以将一个或多个视图分配给passthroughViews   关联的UIPopoverPresentationController对象的属性,   您可以从popoverPresentationController属性获得。

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

在iOS 8.0和更高版本中可用。

参考UIModalPresentationStyle参考


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

***由于未捕获的异常'NSGenericException'而终止应用程序,原因:'UIPopoverPresentationController(***)应该为非nil   在演示发生之前设置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。

Midhun MP answered 2020-02-22T23:24:36Z
7 votes

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;
        }
    }];
}
qix answered 2020-02-22T23:25:24Z
1 votes

如果直接从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];
Abhishek answered 2020-02-22T23:25:44Z
-6 votes

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

[HTTP://呜呜呜.folklore.org/story view.朋友?story=negative_2000_lines_of_code.txt]

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

编辑结束。

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

根据我的代码和我的理解,Popovers是为iPad引入的,并且特定于iPad。 苹果似乎已经改变了这一点。 因此,如果您已经有一个使用如下代码的工作程序:

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

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

Mark Nilsen answered 2020-02-22T23:26:32Z
translate from https://stackoverflow.com:/questions/32818297/how-can-i-fix-the-uipopovercontroller-is-deprecated-warning