launch containing app from iOS8 Custom Keyboard

2020-01-28 02:23发布

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!

11条回答
你好瞎i
2楼-- · 2020-01-28 03:08

In an App Extension (ex: custom keyboard), that would have been handled through UIViewController.extensionContext but as of iOS 8.1.2, the field is nil in the following Swift call:

self.extensionContext?.openURL(appURL, completionHandler: nil)
// Does nothing because extensionContext is nil (iOS 8.1)

Actually, it is not possible either to use Application.sharedApplication.openURL(...) in an App Extension as stated in Apple documentation.

So, as of 8.1.2, the workaround is to use a dumb UIWebView to redirect to the containing app like this:

let webView = UIWebView(frame: CGRectMake(0, 0, 0, 0));
let url = "MyKeyboard://";
let content = "<head><meta http-equiv='refresh' content='0; URL=\(url)'></head>";
webView.loadHTMLString(content, baseURL: nil);
self.view.addSubview(webView);
let delayInSeconds = 2.0
let startTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
dispatch_after(startTime, dispatch_get_main_queue()) { () -> Void in
    webView.removeFromSuperview()
}

Where MyKeyboard:// must be defined accordingly as URL scheme in the containing app.

Please take note that I don't know yet whether this is approved by Apple. Forwarding to apps from custom keyboards may be bad enough for user experience.

查看更多
Rolldiameter
3楼-- · 2020-01-28 03:11

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:

  1. create a url scheme for your app
  2. add a UIWebView to your inputView
  3. 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.

查看更多
够拽才男人
4楼-- · 2020-01-28 03:14

As per Apple review guidelines for Extension, it is now not advised to open external apps from the extension.

For reference please see apple review guidelines

Section 4.4.1

They must not:

  • Include marketing, advertising, or in-app purchases;
  • Launch other apps besides Settings; or
查看更多
不美不萌又怎样
5楼-- · 2020-01-28 03:15

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.                                                                    
查看更多
甜甜的少女心
6楼-- · 2020-01-28 03:15

A Swift 2.2 version, akin to DongHyun Jang's answer for Objective-C:

func webLink(urlString: String) {
    let url = NSURL(string: urlString)
    var responder: UIResponder? = self
    while let r = responder {
        if r.respondsToSelector("openURL:") {
            r.performSelector("openURL:", withObject: url)
            break;
        }
        responder = r.nextResponder()
    }  
}
查看更多
做个烂人
7楼-- · 2020-01-28 03:17

According to Apple's documentation https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/index.html, you should use NSExtensionContext like this:

NSExtensionContext *ctx = [[NSExtensionContext alloc] init];
[ctx openURL:[NSURL URLWithString:@"myapp://"] completionHandler:^(BOOL success){return ;}];
查看更多
登录 后发表回答