Does any one know how to launch the parent app from the app extension\'s view controller?
I just want to launch the main app from its app extension.
Working solution in Swift 3.1 (tested in iOS10):
You need to create your own URL Scheme for your host app, then add this function to your ViewController and call it with openURL("myScheme://myIdentifier")
// Function must be named exactly like this so a selector can be found by the compiler!
// Anyway - it's another selector in another instance that would be "performed" instead.
func openURL(_ url: URL) -> Bool {
var responder: UIResponder? = self
while responder != nil {
if let application = responder as? UIApplication {
return application.perform(#selector(openURL(_:)), with: url) != nil
}
responder = responder?.next
}
return false
}
In the WWDC session Creating Extensions for iOS and OS X, Part 1 around the 22 minute mark the say to use the openURL:completionHandler:
method from the UIViewController's extensionContext to open a custom URL scheme
[self.extensionContext openURL:[NSURL URLWithString:@"your-app-custom-url-scheme://your-internal-url"]
completionHandler:nil];
The documentation is pretty clear on saying that you can use extensionContext openURL within a Today extension. By implication, openURL can only be used in a Today exception and our experiences are proving this to be true--I also can't get it working from within a Share extension.
I would be interested to see if any of these work arounds are accepted by Apple's review process. I doubt it. If Apple wanted it to work, it would have been easy enough for them to allow it.
Apple allows any Today widget to use the openURL:completionHandler: method to open the widget’s own containing app.
If you employ this method to open other apps from your Today widget, your App Store submission might entail additional review to ensure compliance with the intent of Today widgets.
I'm certain this second paragraph was added after Launcher was accepted, rejected, and then later approved for sale.
Here is working solution (tested on iOS 9.2) at least for Keyboard Extension. This category adds special method for access to hidden sharedApplication
object and then call openURL:
on it.
(Of course then you have to use openURL:
method with your app scheme.)
extension UIInputViewController {
func openURL(url: NSURL) -> Bool {
do {
let application = try self.sharedApplication()
return application.performSelector("openURL:", withObject: url) != nil
}
catch {
return false
}
}
func sharedApplication() throws -> UIApplication {
var responder: UIResponder? = self
while responder != nil {
if let application = responder as? UIApplication {
return application
}
responder = responder?.nextResponder()
}
throw NSError(domain: "UIInputViewController+sharedApplication.swift", code: 1, userInfo: nil)
}
}
it is working in my current working app using action extension
1- in parent app plist add custom URL like
2- add both functions in your extension view controller
func openURL(url: NSURL) -> Bool {
do {
let application = try self.sharedApplication()
return application.performSelector(inBackground: "openURL:", with: url) != nil
}
catch {
return false
}
}
func sharedApplication() throws -> UIApplication {
var responder: UIResponder? = self
while responder != nil {
if let application = responder as? UIApplication {
return application
}
responder = responder?.next
}
throw NSError(domain: "UIInputViewController+sharedApplication.swift", code: 1, userInfo: nil)
}
3- call this function in your button action or somewhere you want to do
self.openURL(url: NSURL(string:"openPdf://HomeVC")!)
here homevc is the class name of your View controller which should be presented
4- in your app delegate implement the method like
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
let urlPath : String = url.absoluteString
print(urlPath)
if urlPath.contains("HomeVC"){
//here go to firstViewController view controller
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewController(withIdentifier: "homeVC")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
}
I hope will work fine, can also share data between extension app and parent app
Here is another way to do it:
Build Settings
. Set Require Only App-Extension Safe API
to NO
.UIApplication.shared.openURL(URL(string:"openPdf://")!)
as you normally would do it outside extension to open urls.Note, that you'll get 'openURL' was deprecated in iOS 10.0 warning. So this looks like it is not guaranteed to work in future.
Consider using local Notifications to wake up host app instead of this.