7

Trying to use [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.

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. 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. But an app may wish to share content through a different mechanism than HTTP(S) uploads.

Apple documentation doesn't state that openURL... cannot be used for any particular type of extension. It's hard to know whether this is a bug or intended behavior. There is no official information about this.

user102008
  • 30,736
  • 10
  • 83
  • 104
  • This says a bit about the situation, http://stackoverflow.com/a/24709883/250190. I too am looking to do this, much like the YouTube sharing in iOS 7, I want to provide a `UIAlertController` giving the user an option to see what they just shared. It's a very disconnected experience as it stands. – Chris Wagner Jul 22 '14 at 23:27
  • Possible duplicate of [openURL not work in Action Extension](https://stackoverflow.com/questions/24297273/openurl-not-work-in-action-extension) – bdesham May 14 '19 at 17:57

5 Answers5

8

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
  • Using a dummy NSURLSessionTask to get the application:handleEventsForBackgroundURLSession:completionHandler: method of the UIApplicationDelegate class of your container app to be called. Then, in that method, you can call [[UIApplication sharedApplication] openURL:url] to open whatever you want.

Neither of these methods are perfect, but they do work (not sure if Apple would like them though). 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

Community
  • 1
  • 1
arcticmatt
  • 1,956
  • 1
  • 19
  • 36
3

https://www.jianshu.com/p/a24ae0eb69d5 you must set url scheme first. I have use this and my app was submitted AppStore successful.

 /// 打开主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)

}
evan
  • 318
  • 3
  • 14
1

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. Share, Action, Keyboard, and Document provider do not work for anyone (beta 5).

n8tr
  • 5,018
  • 2
  • 32
  • 33
  • "Share, Action, Keyboard, and Document provider do not work for anyone (beta 5)." Right, but this is not documented anywhere. It could be a bug. – user102008 Aug 07 '14 at 18:50
  • Maybe, but I wouldn't be surprised if it's purposeful based on Apple's intensions on what extensions are supposed to be and do. Also see this thread: http://stackoverflow.com/questions/24297273/openurl-not-work-in-action-extension/25189466#25189466 Maybe they are still deciding too... – n8tr Aug 07 '14 at 19:03
0

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;
  • add a UIWebView and load an HTML string with a link pointing to your app's custom 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.

The click on the web link launches the app, which can fetch the data in NSUserDefaults directly.

theMoonlitKnight
  • 431
  • 8
  • 17
0

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.

This method should also work using the URL scheme from the containing app

halfer
  • 19,824
  • 17
  • 99
  • 186
Julio Bailon
  • 3,735
  • 2
  • 33
  • 34