从iOS8自定义键盘启动包含应用程序

我想启动我的包含应用程序。

我尝试使用URLscheme。

URLscheme从其他地方启动应用程序 – 所以问题不在那里。

看起来像这个对象是零:

self.extensionContext 

因此我不能运行这个方法:

 [self.extensionContext openURL:url completionHandler:nil]; 

我可以启动我的应用程序? URL架构在自定义键盘中工作吗?

谢谢!

试试这个代码

  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]]; } } 

回答我自己的问题:

在iOS8自定义键盘中,extensionContext对象为零,因此我无法使用它来启动包含的应用程序。

我想到的解决方法是:

  1. 为您的应用程序创build一个urlscheme
  2. 添加一个UIWebView到你的inputView
  3. 在web视图中加载您的包含应用程序的urlscheme

我不确定苹果是否会允许这种情况发生,但是现在起作用了。

这里是键盘扩展的工作解决scheme(在iOS 9.2上testing) 。 这个类别增加了访问隐藏的sharedApplication对象的特殊方法,然后调用openURL: (当然,你必须在你的应用程序scheme中使用openURL:方法。)

 // 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) } } 

最近我开发了一些略有不同的方法:

 // 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 } } 

除了“今日”扩展程序之外,Apple不允许任何附加应用信息打开包含的应用。

从指导方针:

“今天”小部件(并且没有其他应用程序扩展types)可以通过调用NSExtensionContext类的openURL:completionHandler:方法来要求系统打开其包含的应用程序。

你可以在这里查看

我试着做最新的xcode 8.2和swift 3.0的解决scheme。

不幸。 我无法得到它的工作。 所以我find了我自己的解决scheme,它在swift 3.0,xcode 8.2中运行的很好

  func openURL(_ url: URL) { return } func openApp(_ urlstring:String) { var responder: UIResponder? = self as UIResponder let selector = #selector(openURL(_:)) while responder != nil { if responder!.responds(to: selector) && responder != self { responder!.perform(selector, with: URL(string: urlstring)!) return } responder = responder?.next } } // Usage //call the method like below //self.openApp(urlString) //URL string need to included custom scheme. //for example, if you created scheme name = customApp //urlString will be "customApp://?[name]=[value]" //self.openApp("customApp://?category=1") 

根据苹果的文档https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/index.html ,你应该像这样使用NSExtensionContext:

 NSExtensionContext *ctx = [[NSExtensionContext alloc] init]; [ctx openURL:[NSURL URLWithString:@"myapp://"] completionHandler:^(BOOL success){return ;}]; 

在一个应用程序扩展(例如:自定义键盘),这将通过UIViewController.extensionContext处理,但从iOS 8.1.2,该字段nil在下面的Swift调用:

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

实际上, Apple应用程序扩展中不能使用Application.sharedApplication.openURL(...)

因此,从8.1.2开始,解决方法是使用一个笨笨的UIWebViewredirect到包含的应用程序,如下所示:

 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() } 

其中MyKeyboard://必须在包含的应用程序中相应地定义为URLscheme。

请注意,我不知道这是否被苹果批准。 从自定义键盘转发到应用程序可能已经足够糟糕的用户体验。

这是我发现打开任何url使用上面所述:

 UIWebView * webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; NSString *urlString = @"https://itunes.apple.com/us/app/watuu/id304697459"; NSString * content = [NSString stringWithFormat : @"<head><meta http-equiv='refresh' content='0; URL=%@'></head>", urlString]; [webView loadHTMLString:content baseURL:nil]; [self.view addSubview:webView]; [webView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:2.0]; 

请注意,在这种情况下,我从UIInputViewController实例化这个调用。

此方法也应该使用来自包含应用程序的URLscheme

注意:截至iOS 8.3苹果已经杀死了这种方法

一个Swift 2.2版本,类似于DongHyun Jang对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() } } 

我挣扎了几天。 我无法在自定义键盘中使用UIWebView。

修复:把它放在viewDidAppear:animation,而不是viewDidLoad(在另一个注意这是键盘的自定义高度的代码应保持在那里)。

码:

 - (void)viewDidAppear:(BOOL)animated { UIWebView * webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; NSString * content = @"<a href='your_app_schema://your_params'>anchor</a>"; [webView loadHTMLString:content baseURL:nil]; [self.view addSubview:webView]; } 

按照Apple的扩展指南,现在build议从扩展中打开外部应用程序。

有关参考请参阅苹果审查指南

第4.4.1节

他们不得:

  • 包括营销,广告或应用内购买;
  • 启动其他应用程序,除了设置; 要么