UIActivity activityViewController 在 iPad 上以模态方式呈现,而不是在弹出窗口中

Posted

技术标签:

【中文标题】UIActivity activityViewController 在 iPad 上以模态方式呈现,而不是在弹出窗口中【英文标题】:UIActivity activityViewController being presented modally on iPad instead of in popover 【发布时间】:2012-11-17 18:56:16 【问题描述】:

ios 6 中使用客户 UIActivity 子类时,可以指定一个自定义视图控制器,当您从初始 UIActionViewController 的视图中选择您的操作时将显示该控制器。为此,您可以从 UIActivity 子类的 activityViewController 方法返回对自定义视图控制器的引用。

根据UIActivity class reference:

activityViewController

此方法的默认实现返回nil。使用视图控制器提供额外 UI 的子类可以覆盖此方法以返回该视图控制器。如果此方法返回一个有效对象,系统会为您呈现返回的视图控制器,而不是调用performActivity 方法。在 iPad 上,您的视图控制器显示在弹出框内。在 iPhone 和 iPod touch 上,您的视图控制器以模态方式呈现。

您的自定义视图控制器应该为您的自定义 UI 提供一个视图,并且应该处理这些视图中的任何用户交互。完成活动后,不要自行关闭视图控制器。相反,调用activityDidFinish: 方法并让系统为您关闭它。

请注意第一段末尾的那一点:在 iPad 上,您的视图控制器显示在弹出框内。在 iPhone 和 iPod touch 上,您的视图控制器以模态方式呈现。

但是,在 iPad 上,activityViewController 返回的视图控制器总是以模态显示,无论我如何呈现 UIActivityViewController(模态或通过弹出框)。通过弹出框呈现时,它会导致它崩溃,因为它认为它没有被关闭。

我做错了什么?这是 iOS 6 中的错误吗?


更新:这是一个说明问题的简单 Xcode 项目。随意克隆它,看看你是否能看出我们哪里出错了:github.com/simonwhitaker/GSActivityDemo

【问题讨论】:

这里有同样的问题。我已经修改了原始帖子以添加一个明确的问题,希望你不介意@Gujamin。 太宽泛了,不具体.... :(我可以开始疯狂的猜测,但我宁愿你编辑问题,也许显示一些代码之类的!-哦,你在使用弧吗?跨度> 这似乎与这个 openradar.appspot.com/12034514 相同,这似乎是由这个 SO 用户提交的(也基于 twitter 句柄)...***.com/users/743524/riley-testut 也许值得给他们发消息。 你解决过这个问题吗?我完全无法让自定义 UIActivity 实现 activityViewController 在 iPad 上正常工作。 iPhone 上没问题。 对于它的价值,这似乎是最简单的解决方案,但仍然有点奇怪:gist.github.com/mluton/3990658 【参考方案1】:

正如我们所说的 UIActivityViewController,它是向用户显示可用活动的视图。苹果声明如下...

您的应用负责配置、呈现和关闭此视图控制器。视图控制器的配置包括指定视图控制器应该操作的数据对象。 (您还可以指定您的应用程序支持的自定义服务的列表。)在呈现视图控制器时,您必须使用当前设备的适当方式来执行此操作。在 iPad 上,您必须在弹出窗口中显示视图控制器。在 iPhone 和 iPod touch 上,您必须以模态方式呈现。

我把最后一行作为你必须处理视图呈现方式的标志,所以我检查代码是否在 iPad 上运行并相应地使用 UIPopover。正如您可以在这里看到的那样...https://github.com/bufferapp/buffer-uiactivity/blob/master/BufferUIActivity/Views/FirstViewController.m 在以下方法中。

-(IBAction)openUIActivityView:(id)sender 

    NSString *text = @"Hello world";
    NSString *url = @"http://bufferapp.com";


    NSArray *activityItems = @[text, url];

    BufferUIActivity *bufferActivity = [[BufferUIActivity alloc] init];

    UIActivityViewController *activityView = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:@[ bufferActivity ]];


    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) 
        [self presentViewController:activityView animated:YES completion:^

        ];
     else 
        // Change Rect to position Popover
        self.popup = [[UIPopoverController alloc] initWithContentViewController:activityView];
        [self.popup presentPopoverFromRect:CGRectMake(self.view.frame.size.width/2, self.view.frame.size.width/2, 100, 100) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    


【讨论】:

嗨,安迪。不,这不是我们要讨论的——我已经澄清了这个问题。我们正在讨论用户选择操作后显示的自定义视图控制器。举一个具体的例子,我正在向我的应用程序添加一个“上传到 Dropbox”操作。所以有一个自定义 UIActivity 子类,它向活动表添加了一个 Dropbox 按钮。当您点击该按钮时,我会显示一个自定义 VC,允许您为文件选择目标文件夹。 VC 应该在 iPad 上的弹出窗口中显示,但始终以模态方式显示。 抱歉,这很奇怪,因为我为 Buffer 所做的 UIActivity 也以模态方式显示在 iPad 上,但 Apple 的 Twitter/Facebook 表格也是如此。我倾向于说这是 iOS6 的问题或文档有误。【参考方案2】:

我认为活动视图控制器未在弹出窗口中显示的问题是一个错误,文档反映了正确的意图。但是,我不知道有什么方法可以解决这个 atm。

然而,关于关闭视图控制器的部分是一个不同的问题。您不应该关闭从 -[UIActivity activityViewController] 返回的视图控制器,但您有负责关闭您呈现的弹出框,这反过来也会从层次结构中删除您的自定义视图控制器. (因为它是这样工作的,我倾向于相信自定义视图控制器通常必须显示在弹出窗口中。)

这是一个来自your example app 的代码示例:

UIActivityViewController *vc = [[UIActivityViewController alloc] initWithActivityItems:activityItems
                                                                 applicationActivities:applicationActivities];

vc.completionHandler = ^(NSString *activityType, BOOL completed)
  [self.activityPopoverController dismissPopoverAnimated:YES];
;

【讨论】:

再想一想,就像 AndyDev 提到的那样,除了打印对话框,所有其他内置活动也以模式屏幕显示。另一个线索是,在呈现自定义视图控制器之前,它会收到 -[UIViewController setModalTransitionStyle:] 消息,表明它确实有意以模态方式呈现它。 很好地解决了视图控制器未关闭的问题。谢谢! 我猜可能有一个私有 API 调用,Apple 忽略了公开,它控制是否以模态方式呈现 activityViewController 或在现有的弹出窗口中。【参考方案3】:

我在 iOS 7 中遇到了同样的问题。在弹出窗口中显示自定义视图的解决方案是在 -(void)performActivity 方法中创建并显示它,而不是在 -(UIViewController *)activityViewController 中返回它。

您可以在此链接下的我的问题/答案中查看示例代码:iOS 7 custom UIActivity as popover

【讨论】:

【参考方案4】:

我刚刚遇到了同样的问题,但通过将 ViewController 设置为:

[yourViewController setModalPresentationStyle:UIModalPresentationPageSheet];

- (UIViewController *)activityViewController

希望对你有帮助

【讨论】:

问题是它应该出现在 iPad 上的弹出窗口中。这不会发生,尤其是如果您通过将演示文稿样式设置为页面表来强制它。

以上是关于UIActivity activityViewController 在 iPad 上以模态方式呈现,而不是在弹出窗口中的主要内容,如果未能解决你的问题,请参考以下文章

具有多个操作的 UIActivity

覆盖由内置 UIActivity 类型执行的活动

UIActivity 自定义 activityViewController 在 iPad 上崩溃

自定义 UIActivity 的主题

自定义 UIActivity :图像图标反转颜色

在 UIActivity:activityViewController 期间显示 UIAlertView