简体   繁体   English

openURL 在共享扩展中不起作用

[英]openURL doesn't work in Share extension

Trying to use [self.extensionContext openURL:... completionHandler:...];尝试使用[self.extensionContext openURL:... completionHandler:...]; in an iOS 8 Share extension to open the containing app never opens the app, and always calls the completion handler with success = NO.在 iOS 8 Share 扩展中打开包含的应用程序永远不会打开应用程序,并且总是以成功 = NO 调用完成处理程序。

Here is the same issue with Action extensions, but I think it is more reasonable for Share extensions to be able to open the containing app than Action extensions. 是 Action 扩展的相同问题,但我认为 Share 扩展能够打开包含的应用程序比 Action 扩展更合理。 The point of a Share extension is to upload a potentially large piece of data, and the only way to do that without opening the app is through NSURLSession , which can only do HTTP(S) uploads. Share 扩展的目的是上传潜在的大量数据,而无需打开应用程序就可以做到这一点的唯一方法是通过NSURLSession ,它只能进行 HTTP(S) 上传。 But an app may wish to share content through a different mechanism than HTTP(S) uploads.但是应用程序可能希望通过与 HTTP(S) 上传不同的机制来共享内容。

Apple documentation doesn't state that openURL... cannot be used for any particular type of extension. Apple 文档没有说明openURL...不能用于任何特定类型的扩展。 It's hard to know whether this is a bug or intended behavior.很难知道这是一个错误还是预期的行为。 There is no official information about this.没有关于此的官方信息。

Here are some possible workarounds... Communicating with/opening Containing app from Share extension以下是一些可能的解决方法... 与共享扩展中的包含应用程序通信/打开包含应用程序

The ones that actually work can be summed up as:实际工作的可以总结为:

  • Using a UIDocumentInteractionController and registering your container app with a special extension type to open your container app from your extension使用 UIDocumentInteractionController 并使用特殊扩展类型注册您的容器应用程序以从您的扩展程序打开您的容器应用程序
  • Using a dummy NSURLSessionTask to get the application:handleEventsForBackgroundURLSession:completionHandler: method of the UIApplicationDelegate class of your container app to be called.使用虚拟 NSURLSessionTask 获取要调用的容器应用程序的 UIApplicationDelegate 类的application:handleEventsForBackgroundURLSession:completionHandler:方法。 Then, in that method, you can call [[UIApplication sharedApplication] openURL:url] to open whatever you want.然后,在该方法中,您可以调用[[UIApplication sharedApplication] openURL:url]来打开您想要的任何内容。

Neither of these methods are perfect, but they do work (not sure if Apple would like them though).这些方法都不是完美的,但它们确实有效(但不确定 Apple 是否会喜欢它们)。 For more details you can check out the link.有关更多详细信息,您可以查看链接。 Hope this helps :)希望这可以帮助 :)

Edit: You can also use a UIWebView as described https://stackoverflow.com/a/24614589/3923882编辑:您也可以按照https://stackoverflow.com/a/24614589/3923882所述使用 UIWebView

The documentation does indicate that the "extension point determines whether to support this method" and in practice only those who use the Today Extension are able to launch their host app using openUrl.该文档确实表明“扩展点决定是否支持此方法”,实际上只有使用 Today Extension 的人才能使用 openUrl 启动其主机应用程序。 Share, Action, Keyboard, and Document provider do not work for anyone (beta 5).共享、操作、键盘和文档提供程序不适用于任何人(测试版 5)。

I'm using this method which does not involve any background task:我正在使用这种不涉及任何后台任务的方法:

  • use a UIViewController (instead of the default SLComposeServiceViewController ) subclass for share extension in order to add custom layout;使用UIViewController (而不是默认的SLComposeServiceViewController )子类进行共享扩展以添加自定义布局;
  • add a UIWebView and load an HTML string with a link pointing to your app's custom URL;添加一个UIWebView并加载一个 HTML 字符串,其中包含一个指向您应用的自定义 URL 的链接;
  • implement webView:shouldStartLoadWithRequest:navigationType: method to intercept the click on the link and before returning YES use NSUserDefaults with initWithSuiteName: (providing the name of the app group) to save data in the container shared by your extension and the containing app.实现webView:shouldStartLoadWithRequest:navigationType:方法来拦截对链接的点击,在返回 YES 之前使用NSUserDefaultsinitWithSuiteName:提供应用程序组的名称)将数据保存在您的扩展程序和包含应用程序共享的容器中。

The click on the web link launches the app, which can fetch the data in NSUserDefaults directly.单击 web 链接启动应用程序,它可以直接获取NSUserDefaults的数据。

This is what I use from my keyboard extension:这是我从键盘扩展中使用的:

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

Please note that in this case I am instantiating this call from the UIInputViewController.请注意,在这种情况下,我从 UIInputViewController 实例化此调用。

This method should also work using the URL scheme from the containing app此方法也应该使用包含应用程序的 URL 方案

https://www.jianshu.com/p/a24ae0eb69d5 you must set url scheme first. https://www.jianshu.com/p/a24ae0eb69d5你必须先设置url scheme。 I have use this and my app was submitted AppStore successful.我已经使用了这个,我的应用程序已成功提交 AppStore。

 /// 打开主APP
/// - Parameter type: 打開類型
func openContainerApp(type: String) {

    let scheme = "yoururlscheme://type"

    let url: URL = URL(string: scheme)!

    let context = NSExtensionContext()

    context.open(url, completionHandler: nil)

    var responder = self as UIResponder?

    let selectorOpenURL = sel_registerName("openURL:")

    while (responder != nil) {

        if responder!.responds(to: selectorOpenURL) {

            responder!.perform(selectorOpenURL, with: url)

            break

        }

        responder = responder?.next

    }

    self.extensionContext?.completeRequest(returningItems: [], completionHandler: nil)

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM