从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对象为零,因此我无法使用它来启动包含的应用程序。
我想到的解决方法是:
- 为您的应用程序创build一个urlscheme
- 添加一个UIWebView到你的inputView
- 在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开始,解决方法是使用一个笨笨的UIWebView
redirect到包含的应用程序,如下所示:
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节
他们不得:
- 包括营销,广告或应用内购买;
- 启动其他应用程序,除了设置; 要么