launch containing app from iOS8 Custom Keyboard
I want to launch my containing app.
I tried using URL schemes.
The URL scheme launched the app from other places - so the problem is not there.
Looks like this object is nil:
self.extensionContext
thus i can't run this method:
[self.extensionContext openURL:url completionHandler:nil];
Can I launch my app? Do URL Schemes work in a custom keyboard?
thanks!
Try this code
UIResponder* responder = self;
while ((responder = [responder nextResponder]) != nil)
{
NSLog(@"responder = %@", responder);
if([responder respondsToSelector:@selector(openURL:)] == YES)
{
[responder performSelector:@selector(openURL:) withObject:[NSURL URLWithString:urlString]];
}
}
To answer MY OWN question:
In an iOS8 custom keyboard, the extensionContext object is nil, thus I can't use it to launch the containing app.
The workaround I came up with is:
- create a url scheme for your app
- add a UIWebView to your inputView
- load the url scheme for your containing app in the webview
I'm not sure if Apple will allow this to happen, but it works now.
Here is working solution (tested on iOS 9.2) 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.)
// Usage:
// UIInputViewController.openURL(NSURL(string: "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)
}
}
Lately I developed slightly different approach:
// Usage:
// UIApplication.🚀sharedApplication().🚀openURL(NSURL(string: "your-app-scheme://")!)
extension UIApplication {
public static func 🚀sharedApplication() -> UIApplication {
guard UIApplication.respondsToSelector("sharedApplication") else {
fatalError("UIApplication.sharedKeyboardApplication(): `UIApplication` does not respond to selector `sharedApplication`.")
}
guard let unmanagedSharedApplication = UIApplication.performSelector("sharedApplication") else {
fatalError("UIApplication.sharedKeyboardApplication(): `UIApplication.sharedApplication()` returned `nil`.")
}
guard let sharedApplication = unmanagedSharedApplication.takeUnretainedValue() as? UIApplication else {
fatalError("UIApplication.sharedKeyboardApplication(): `UIApplication.sharedApplication()` returned not `UIApplication` instance.")
}
return sharedApplication
}
public func 🚀openURL(url: NSURL) -> Bool {
return self.performSelector("openURL:", withObject: url) != nil
}
}