为啥 UIActivityViewController 会在 Presenter 上调用 viewWillDisappear()?
Posted
技术标签:
【中文标题】为啥 UIActivityViewController 会在 Presenter 上调用 viewWillDisappear()?【英文标题】:Why does UIActivityViewController call viewWillDisappear() on the presenter?为什么 UIActivityViewController 会在 Presenter 上调用 viewWillDisappear()? 【发布时间】:2019-10-18 17:19:56 【问题描述】:我正在展示一个 UIActivityViewController 来分享来自 URL 的 .mp4 视频:
let viewController: UIViewController = ... // the presenting view controller
let url: URL = ... // local file
let activityController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
viewController.present(activityController, animated: false, completion: nil)
选择“保存视频”选项时,保存视频,但介绍UIViewController
消失(我可以看到.viewWillDisappear()
in conte。)
如何让演示中的UIViewController
不消失?
请注意,我尝试过的所有其他共享选项都没有这个问题(消息、空投、instagram)。
我尝试设置sourceView
和sourceRect
,但似乎没有帮助。
activityController.popoverPresentationController?.sourceView = viewController.view!
activityController.popoverPresentationController?.sourceRect = viewController.view!.frame
我已查找错误,但没有找到任何错误:
activityController.completionWithItemsHandler = (a: UIActivity.ActivityType?, b: Bool, c: [Any]?, d: Error?) in
if let error = d
print(error)
另外,我所有的 UIViewController
生命周期覆盖都调用它们的超级,即:
override func viewWillDisappear(_ animated: Bool)
super.viewWillDisappear(animated)
这是它的样子:
它正在降低我的整个视野!
不管怎样,viewController
是通过调用故事板中设置的 segue 来设置的:
class LaunchController : UIViewController
var performedSegue = false
override func viewDidLayoutSubviews()
if !performedSegue
self.performSegue(withIdentifier: "main", sender: self)
performedSegue = true
【问题讨论】:
我尝试使用单个ViewController
制作一个简单的示例,但无法重现该问题,视频已成功保存,并且未调用 ViewWillDisappear
方法。你是如何展示你的模态视图控制器的?单视图控制器项目也会出现同样的错误吗?
哇哦,真快!很好的测试。在问题末尾添加了更多信息。
是的,我现在可以重现,这仅在您以模态方式呈现 ViewController
时发生。奇怪的问题。
尝试在你的activityController上设置modalPresentationStyle
【参考方案1】:
看起来这个“功能”是苹果在 ios 13 中引入的。我测试了 这在 iOS 12 上并且呈现的 ViewController 不会消失。
我跟踪了调用堆栈,当保存到相机胶卷成功时,UIActivityViewController 似乎在呈现视图控制器(或者它是 UINavigationController)上调用了dismiss。
我不知道如何防止这种情况发生,因为它是 Apple 私有 API,并且文档中没有关于此的任何内容。我发现的唯一方法是在呈现 UIActivityViewController 时设置某种标志 savingToCameraRoll
并将其设置为 true
,在呈现 ViewController 时覆盖 dismiss
方法,然后在 dismiss
中检查此标志。
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil)
if !savingToCameraRoll
// Dismiss view controller if UIActivityViewController not in use
super.dismiss(animated: animated, completion: completion)
// Handle UIActivityViewController dismiss attempt.
// If you do nothing, the presenting ViewController should not be dismissed.
您还应该记住在completionWithItemsHandler
中将savingToCameraRoll
设置为false
。
【讨论】:
【参考方案2】:在故事板中,我将呈现的 ViewController 标记为“是初始视图控制器”,而不是通过 segue 呈现它。这为我解决了这个问题(尽管它是一种一般情况下不起作用的解决方法)。
【讨论】:
以上是关于为啥 UIActivityViewController 会在 Presenter 上调用 viewWillDisappear()?的主要内容,如果未能解决你的问题,请参考以下文章
为啥使用 glTranslatef?为啥不直接更改渲染坐标?
为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?