I'm trying to implement “Save image to Library” function and then return back to the current view controller, but on a new iOS 13 it dismisses back to the view controller that presented the current one:
PHPhotoLibrary.requestAuthorization({(_ status: PHAuthorizationStatus) -> Void in }) let shareItems: Array = [newImg,"Hello"] as [Any] let activityController = UIActivityViewController(activityItems: shareItems, applicationActivities: nil) if UIDevice.current.userInterfaceIdiom == .pad { activityController.popoverPresentationController?.sourceView = saveButton } present(activityController, animated: true)
Swift version of @KDP's solution:
let fakeViewController = TransparentViewController() fakeViewController.modalPresentationStyle = .overFullScreen activityViewController.completionWithItemsHandler = { [weak fakeViewController] _, _, _, _ in if let presentingViewController = fakeViewController?.presentingViewController { presentingViewController.dismiss(animated: false, completion: nil) } else { fakeViewController?.dismiss(animated: false, completion: nil) } } present(fakeViewController, animated: true) { [weak fakeViewController] in fakeViewController?.present(activityViewController, animated: true, completion: nil) }
fakeViewController
gets either dismissed by activity completion, or we need to dismiss it in completion.
I can confirm that this bug is still present in iOS 13.3.1. The following workaround is a Swift version of franze's solution. I prefer this approach, as it doesn't make any further assumptions on the view controller hierarchy and doesn't use method swizzling.
Using this additional UIWindow
breaks the Cancel button of the UIActivityViewController
on iOS 12 and earlier, so I added a check for the OS version.
private let activityWindow: UIWindow = { let window = UIWindow(frame: UIScreen.main.bounds) window.rootViewController = UIViewController() return window }() func showActivityController() { let activityViewController = UIActivityViewController(/* ... */) activityViewController.completionWithItemsHandler = { // ... UIApplication.shared.delegate?.window??.makeKeyAndVisible() } // Use this workaround only on iOS 13 if ProcessInfo.processInfo.operatingSystemVersion.majorVersion == 13 { activityWindow.makeKeyAndVisible() activityWindow.rootViewController?.present(activityViewController, animated: true) } else { present(activityViewController, animated: true) } }
Update: Apparently, this solution doesn't work reliably on iPads. It looks like on iPad the UIActivityViewController
is presented differently and as soon as it's visible on screen, no touch events are registered, effectively freezing the app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With