iOS Share Extension: get URL of page when sharing via context menu in Safari

送分小仙女□ 提交于 2020-05-09 19:09:21

问题


What I want

I'm trying to achieve the following user flow:

  1. User is browsing a webpage in iOS Safari.
  2. User selects some content (text and images) and waits for context menu to appear.
  3. User selects the "Share..." item.
  4. User selects my App Extension in the sharing menu that comes up from the bottom.
  5. Selected content and the webpage URL is shared to a remote server via an HTT call.

What I tried

I made a Share extension via Xcode. Here's the NSExtension section of my info.plist:

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionActivationRule</key>
        <dict>
            <key>NSExtensionActivationSupportsWebPageWithMaxCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsText</key>
            <true/>
            <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
            <integer>1</integer>
        </dict>
        <key>NSExtensionJavaScriptPreprocessingFile</key>
        <string>test</string>
    </dict>
    <key>NSExtensionMainStoryboard</key>
    <string>MainInterface</string>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.share-services</string>
</dict>

Here's the test.js file:

var GetURL = function() {};
GetURL.prototype = {
run: function(arguments) {
    arguments.completionFunction({"URL": document.URL});
}
};
var ExtensionPreprocessingJS = new GetURL;

I expected the following result: in viewDidLoad method extensionContext?.inputItems would provide me with several input items, through which I would be able to get the selected content and the web URL.

What goes wrong

In viewDidLoad method extensionContext?.inputItems provides me with only one item -- the plain text representation of the selected content (even when I selected images and text at the same time). I can live with plain text, but I need the webpage URL.

My question

How can I get URL of the opened webpage when using a Share extension to share selected content via context menu in iOS Safari?


回答1:


I've spent an embarrassingly large part of an afternoon reading the docs on this and trying different permutations of extensions, as I was looking to do exactly (I think) what you were trying to do.

I've concluded that this exact flow cannot be achieved on iOS. If the user selects text and uses the context menu (i.e. "Copy", "Look Up", "Share"...), the only thing your extension will ever receive is an NSItemProvider with the text that they selected, i.e. not a plist with the results of the preprocessing javascript. When they select Share from that menu, the extension shows up if and only if you've got NSExtensionActivationSupportsText set to YES in the extension's Info.plist file.

In order to run the preprocessing javascript, an extension has to have NSExtensionActivationSupportsWebPageWithMaxCount set to a value greater than 0, per the docs. If an extension gets called via the selected text context menu, that javascript file never runs.

However, it's possible to get pretty close to the desired flow. If the user is in Safari, and selects some text, and then, instead of tapping "Share" in the context menu, taps the Share icon at the bottom of the Safari UI, then the NSItemProvider comes back as a plist and the NSExtensionJavaScriptPreprocessingFile gets run. My javascript file looks like the following:

var Share = function() {};

Share.prototype = {
  run: function(arguments) {
    arguments.completionFunction({"URL": document.URL, "selectedText": document.getSelection().toString()});
  },
  finalize: function(arguments) {
    // alert shared!
  }
};

var ExtensionPreprocessingJS = new Share

which means that the plist object returned to the extension has both the URL of the page and the selectedText.

If the only purpose of an extension is the share URLs, and plain text without a URL isn't a sensical use case, you should probably not have NSExtensionActivationSupportsText set to YES. For example, an app like Pocket has it enabled, but if a user selects some text in Safari and then tries to share via the context menu, Pocket can't do anything meaningful with just the plaintext and no page URL, so it just pops up a pretty cryptic error message.

I've published the code for my extension as well if you want to have a look.




回答2:


Swift 3

Try something along the lines of:

override func didSelectPost() {
    if let item = extensionContext?.inputItems.first as? NSExtensionItem,
        let itemProvider = item.attachments?.first as? NSItemProvider,
        itemProvider.hasItemConformingToTypeIdentifier("public.url") {
        itemProvider.loadItem(forTypeIdentifier: "public.url", options: nil) { (url, error) in
            if let shareURL = url as? URL {
                // do what you want to do with shareURL
            }
            self.extensionContext?.completeRequest(returningItems: [], completionHandler:nil)
        }
    }
}

"public.url" can be replaced with the kUTTypeURL String imported from MobileCoreServices



来源:https://stackoverflow.com/questions/44218809/ios-share-extension-get-url-of-page-when-sharing-via-context-menu-in-safari

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!