I am presenting a UIActivityViewController to share an .mp4 video from a URL:
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)
When the "save video" option is selected, the video is saved, but the presenting UIViewController
disappears (and I can see that .viewWillDisappear()
is called on it.)
How do I make the presenting UIViewController
not disappear?
Note that all of the other share options that I've tried do not have this problem (messages, airdrop, instagram).
I have tried to set the sourceView
and sourceRect
, but it does not seem to help.
activityController.popoverPresentationController?.sourceView = viewController.view!
activityController.popoverPresentationController?.sourceRect = viewController.view!.frame
I've looked for errors, but didn't find any:
activityController.completionWithItemsHandler = { (a: UIActivity.ActivityType?, b: Bool, c: [Any]?, d: Error?) in
if let error = d {
print(error)
}
}
Also, all of my UIViewController
lifecycle overrides call their super, i.e.:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
This is what it looks like:
It's bringing down my entire view with it!
For what it's worth, viewController
is setup by calling a segue that is setup in a storyboard:
class LaunchController : UIViewController {
var performedSegue = false
override func viewDidLayoutSubviews() {
if !performedSegue {
self.performSegue(withIdentifier: "main", sender: self)
performedSegue = true
}
}
}
It looks like this "feature" was introduced by Apple in iOS 13. I tested this on iOS 12 and the presenting ViewController does not disappear.
I traced the call stack and it appear that UIActivityViewController is calling dismiss on presenting view controller (or it's UINavigationController) when saving to camera roll succeeds.
I don't know the way to prevent this since it's Apple private API and there's nothing in documentation about this. The only way I found, is to to set some kind of flag savingToCameraRoll
and set it to true
when presenting UIActivityViewController, override dismiss
method on presenting ViewController and then check this flag inside 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.
}
You should also remember to set savingToCameraRoll
to false
in completionWithItemsHandler
.