UIActivity activityViewController 没有在 iPad 上关闭

Posted

技术标签:

【中文标题】UIActivity activityViewController 没有在 iPad 上关闭【英文标题】:UIActivity activityViewController not dismissing on iPad 【发布时间】:2012-09-22 12:04:34 【问题描述】:

我有一个 UIActivity 子类,它创建了自己的 activityViewController

- (UIViewController *)activityViewController 
    WSLInProgressViewController* progressView = [[[WSLInProgressViewController alloc] init] autorelease];
    progressView.message = [NSString stringWithFormat:NSLocalizedString(@"Posting to %@...",@"Posting to..."),
                        self.activityType];

    return progressView;

我已经添加了一个完整的repro on GitHub。


根据文档,您不应该手动关闭它。相反,操作系统会在您调用 activityDidFinish: 时执行此操作。这在 iPhone 上运行时效果很好。

当我说“有效”时,这就是我所期待的事件序列(在 iPhone 上可以看到):

    显示UIActivityViewController 用户按下我的自定义活动 我的视图控制器出现了 我打电话给activityDidFinish: 我的自定义视图控制器已关闭 UIActivityViewController 也被驳回

但是,当我在 iPad 模拟器上运行相同的代码时——唯一的区别是我将UIActivityViewController 放在弹出窗口中,正如文档所说的那样——activityViewController 永远不会关闭。

正如我所说,这是 代码 wo/popUP 在 iPhone 上工作,我已经逐步完成了代码,所以我知道 activityDidFinish: 正在被调用。

我发现这个雷达在谈论same problem in ios6 beta 3,但它似乎是这样基本的功能,以至于我怀疑我的代码而不是操作系统中存在错误(另请注意,它与 Twitter 和 Facebook 功能一起正常工作!)。


我错过了什么吗?在 UIPopoverViewController 中运行时,我是否需要在 activityViewController 中做一些特别的事情? “流程”应该在 iPad 上会有所不同吗?

【问题讨论】:

你是如何关闭 UIPopoverViewController 的?根据过去的经验,您需要通过调用 [myPopoverControler dismissPopoverAnimated]; 来明确地关闭弹出框本身; 你想出解决方案了吗?这似乎是一个严重的错误。基本上这意味着实现activityViewController 的自定义 UIActivity 在 iPad 上是无用的。 @matt 下面接受的答案是我见过的最好的答案。我将 Radar 12545554 用于“不消除”错误,将 12545600 用于“出现模态”。如果你有机会,请欺骗。他们俩都还开着。对于我的应用,我最终没有使用activityViewController 谢谢@StephenDarlington - 我确实提交了一个错误报告。您在下面接受的答案一次有效,但第二次无效,如果您检查所涉及的各个类的 dealloc,您会发现内部发生了严重的内存管理错误。 【参考方案1】:

仅当您的“活动”控制器直接呈现,而不是包含在任何东西中时,才会出现自动关闭。因此,在显示包含它的弹出窗口之前,添加一个完成处理程序

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

你会很好的。

【讨论】:

是的,成功了。 (它仍然显示为模态形式而不是弹出窗口,但这是一个不同的问题......) 这似乎只会延迟问题。第二次选择自定义活动时,应用程序崩溃。据我所知,第一个 UIActivityViewController 和 UIViewController 已泄漏,当您尝试创建第二个时,它会因一些陈旧的数据而崩溃。有谁知道如何解决这个问题? @ragfield 你是对的。这种行为也显示在我的测试应用程序中。我为此提出了一个雷达。 Apple 尚未作出回应。 还可以尝试在activityViewController 和自定义UIActivity 中记录dealloc。它在activityViewController 上被调用了两次,同时 UIActivity 对象正在泄漏。这是非常非常错误的。 iPad 上的管理方式有问题。 这只是真正问题的补丁/解决方法。有关真正的根本原因,请参阅下面的 eploko 答案。根据 Apple 的文档,您不应该直接关闭 UIActivityViewController。当你直接关闭它时,你会注意到关闭动画没有正确显示。【参考方案2】:

我看到这个问题已经很老了,但我们一直在调试相同的 view-controller-not-dismissing 问题,我希望我的回答能提供一些额外的细节和比手动调用 -dismissPopoverAnimated: 更好的解决方案。

关于 UIActivity 的文档非常稀少,虽然它暗示了实现的结构方式,但问题表明它并不那么明显。

您应该注意到的第一件事是文档声明您应该无论如何手动关闭视图控制器。这实际上是正确的。

文档没有说什么,以及当您遇到调试 non-dissmissing-view-controller 问题时可以观察到的事情是,iOS 在以下情况下调用您的 -activityViewController 方法它需要对主题视图控制器的引用。事实证明,可能仅在 iPad 上,iOS 实际上并没有将返回的视图控制器实例存储在其结构中的任何位置,然后,当它想要关闭视图控制器时,它只是向您的 -activityViewController 询问该对象,然后关闭它。因此,在第一次调用该方法时(当它被显示时)实例化的视图控制器永远不会被解除。哎哟。这就是问题的原因。

我们如何正确解决这个问题?

进一步浏览UIActivity 文档可能会偶然发现-prepareWithActivityItems: 方法。特定提示位于以下文本中:

如果您的服务实现需要向用户显示额外的 UI,您可以使用此方法来准备您的视图控制器对象并使其可从 activityViewController 方法中使用。

因此,我们的想法是在 -prepareWithActivityItems: 方法中实例化您的视图控制器并将其处理为实例变量。然后只需从您的 -activityViewController 方法返回相同的实例。

鉴于此,在您调用 -activityDidFinish: 方法后,视图控制器将被正确隐藏,无需任何进一步的手动干预。

宾果游戏。

注意!进一步挖掘这一点,-prepareWithActivityItems: 应该在每次调用它时实例化一个新的视图控制器。如果您以前创建了一个,则只需重新使用它即可。在我们的例子中,如果我们不这样做,它就会很高兴地崩溃。

我希望这对某人有所帮助。 :)

【讨论】:

完美解释!感谢您花时间在这里真正找到真正的根本原因。【参考方案3】:

我遇到了同样的问题。它为我解决了将 activityViewController 保存为成员并返回存储的控制器的问题。 Activity 返回新对象并在新对象上调用解除。

    - (UIViewController *)activityViewController 
        if (!self.detaisController) 
            // create detailsController
        
        return self.detailsController;
    

【讨论】:

【参考方案4】:

我通过 UIActivity 到另一个视图然后调用以下...

[myActivity activityDidFinish:YES];

这适用于我的设备以及模拟器。确保您没有像我之前所做的那样覆盖 UIActivity .m 文件中的 activityDidFinish 方法。你可以看到我使用的代码here。

【讨论】:

感谢您的回答,但是,不,我没有覆盖activityDidFinish:。正如我在问题中所说,相同的代码在 iPhone(模拟器和设备)上运行良好,但在 iPad(模拟器和设备)上运行良好。 奇怪,刚刚仔细检查了我们的项目,它在 iPhone 和 iPad 模拟器上都可以正常工作。 我不相信示例代码是正确的——即使 Apple 的文档说不这样做,它也会关闭视图控制器——而且它似乎也没有像我预期的那样工作。 ..关闭活动后菜单不会消失。话虽如此,我将扩展问题以解释我认为应该发生的事情;也许我错了。 删除该行也有效,我的项目也支持 iOS5,因此我需要找到一种方法来确保仅在需要时调用它。重新阅读您的问题,这正是它应该如何工作,并使用 Facebook 和 Twitter 这样做。你的项目在 GitHub 上吗?我们正在 uiactivities.com 上建立一系列活动,我很高兴为您服务。 我不能(轻松)将我的实际代码放在 GitHub 上,但我刚刚添加了一个示例项目来演示该问题:github.com/sdarlington/ActivityViewContollerBug【参考方案5】:

一种解决方法是要求调用 ViewController 通过- (void)performActivity 对目标 ViewController 执行 segue,尽管 Apple 不建议这样做。

例如:

- (void)performActivity


    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
    
        [self.delegate performSomething]; // (delegate is the calling VC)
        [self activityDidFinish: YES];
    


- (UIViewController *)activityViewController

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
    
        UIViewController* vc=XXX;

        return vc;
    
    else
    
        return nil;
    

【讨论】:

【参考方案6】:

你使用故事板吗?也许在您的 iPad 故事板中,UIActivityIndicatorView 没有勾选“停止时隐藏”?

希望对您有所帮助!

【讨论】:

好主意,但没有。没有故事板或 XIB。 WSLInProgressViewController 派生自 UIViewController 而不是 UIActivityIndi​​catorView(我假设这就是您所说的 UIActivityView 的意思?)。 啊,好吧,太糟糕了:(确实,对不起,我的意思是UIActivityIndicatorView确实。【参考方案7】:

所以我遇到了同样的问题,我有一个带有自定义 activityViewController 的自定义 UIActivity,当它以模态方式呈现时,无论我尝试什么都不会关闭。为了使用户的体验保持不变,我选择采用的解决方法是仍然使用自定义 UIActivity,但给该活动一个委托。所以在我的 UIActiviy 子类中,我有以下内容:

- (void)performActivity

    if ([self.delegate respondsToSelector:@selector(showViewController)]) 
        [self.delegate showViewController];    
    

    [self activityDidFinish:YES];


- (UIViewController *)activityViewController

    return nil;

然后,我将显示 UIActivityViewController 的视图控制器设为委托,并显示视图控制器,否则您将在委托方法中的 activityViewController 中显示。

【讨论】:

【参考方案8】:

最后发布呢?使用非弧项目!

[progressView release];

很多用户和你有同样的问题!另一种解决方案是:

UIActivityIndicatorView *progress= [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(125, 50, 30, 30)];
progress.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
[alert addSubview:progress];
[progress startAnimating];

如果您使用情节提要,请确保当您单击活动时。点击“停止时隐藏”!

希望对您有所帮助...

【讨论】:

感谢您的回答,但是...progressView 是自动发布的,因此添加新版本会导致其过度发布。 WSLInProgressViewController 不仅仅是一个花哨的UIActivityIndicatorView 所以它没有startAnimating 方法。

以上是关于UIActivity activityViewController 没有在 iPad 上关闭的主要内容,如果未能解决你的问题,请参考以下文章

具有多个操作的 UIActivity

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

UIActivity 自定义 activityViewController 在 iPad 上崩溃

自定义 UIActivity 的主题

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

在 UIActivity:activityViewController 期间显示 UIAlertView