How a Share Extension Opens Its Host App
The query is how a share extension, launched from a share sheet in a “international” app, i.e. an app that’s not the extension host app, could be made to summon its host app to the entrance.
The quick reply is that it might’t. That is not what a share extension is for. Nonetheless, many apps do the truth is have share extensions that do that; and the query is: how do they do it?
So let’s begin with a disclaimer: don’t really do what I am about to explain! It is unlawful and Apple does not need you to do it.
Half One: The Invisible Share Extension
The primary drawback is {that a} share extension has an interface, which goes to be introduced within the “international” app the place the share sheet launches the share extension. However we do not need this to occur, as a result of our share extension goes to modify to the host app as a substitute; the interface the consumer will see just isn’t a mere view controller’s view in entrance of the “international” app, however the precise host app.
The key to fixing this drawback is to acknowledge that, though we can not stop the share extension from presenting an interface, we can make that interface invisible. There are two components to doing this:
-
First, make the share extension’s interface consist solely of a view controller with a transparent, empty view. That approach, when the view is introduced in entrance of the share sheet within the “international” app, it will likely be invisible.
-
Second, within the share extension’s Information.plist, within the NSExtensionAttributes dictionary, add the
NSExtensionActionWantsFullScreenPresentation
key and set its worth, a Boolean, to YES. That approach, when the invisible view is introduced in entrance of the share sheet, the “international” app displaying the share sheet will not “shrink” to accomodate the introduced view as a “sheet”; the presentation can be.fullScreen
and so the “international” app will stay full sized.
Half Two: The Customized Scheme
Our extension goes to run inside a “international” app, successfully as if it had been a part of the “international” app. How can a “international” app summon our app to the entrance? One answer is that our app can have a customized URL scheme, which the “international” app will inform the runtime to open.
So, within the app’s Information.plist, we’ll outline a customized URL scheme. (Apple has a doc, Defining a customized URL scheme to your app, that describes how to do that.)
Let’s faux that your customized scheme is mycustomscheme
.
Half Three: The Extension Opens the Scheme
So as to summon the host app, the code in your extension’s view controller should open the host app’s customized scheme. Or, extra particularly, it should inform the host app’s shared UIApplication occasion to open the host app’s customized scheme, by calling this UIApplication occasion methodology:
func open(
_ url: URL,
choices: [UIApplication.OpenExternalURLOptionsKey : Any] = [:],
completionHandler completion: (@MainActor @Sendable (Bool) -> Void)? = nil
)
However an extension can not communicate of UIApplication.shared
— the compiler prevents it. Due to this fact we should (illegally) work round this restriction. A lot of the different solutions on this web page describe how to do that, though a few of them are additionally loaded with pointless cruft. It’s ample to have, in your share extension’s view controller, a way like this:
func openURL(_ url: URL?) {
guard let url else { return }
var responder: UIResponder? = self
whereas responder != nil {
if let software = responder as? UIApplication {
software.open(url, choices: [:], completionHandler: nil)
return
}
responder = responder?.subsequent
}
}
Within the share extension’s view controller, you will name that methodology, with the URL akin to your customized scheme, i.e. URL(string: "mycustomscheme:")
.
Closing Remarks: Timing is The whole lot
I depart to you the query of how you will talk info from the share extension to the host app. Sometimes, your host app and share extension can have the identical app group, and the share extension will drop info, as a file or information, in that app group’s containerURL
listing, the place the host app will look forward to finding it.
Your host app will then wish to reply when the customized scheme URL arrives, by trying the app group’s containerURL
and retrieving the knowledge. The Apple doc that I already linked to tells you the best way to detect that your app has been despatched its customized scheme URL; in a contemporary, scene-based app, you’ll want to implement each scene(_:willConnectTo:choices:)
and scene(_:openURLContexts:)
within the scene delegate.
Returning, lastly, to your share extension, understand that the share extension view controller has obligations to meet. An excellent strategy is likely to be to implement beginRequest(with:)
to save lots of off the NSExtensionContext in property, and to deposit the extension context’s connected info into the app group’s containerURL
listing; after which implement viewWillAppear
to name our openURL
methodology (see above) and name the extension context’s completeRequest
:
override func viewWillAppear(_ animated: Bool) {
tremendous.viewWillAppear(animated)
context?.completeRequest(returningItems: nil) { [weak self] _ in
self?.openURL(URL(string: "mycustomscheme:"))
}
}
The explanation for this association is that our openURL
relies upon upon the view controller being within the view controller hierarchy, in order that it’s a part of the UIResponder chain and we will work our approach up the chain to search out the shared UIApplication occasion. viewWillAppear
is the earliest second we will assure this.