iOS 共享扩展:在 Safari 中通过上下文菜单共享时获得 URL 页面

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

我想要的

我正在尝试实现以下用户流程:

  1. 用户正在 iOS Safari 中浏览网页。
  2. 用户选择一些内容(文本和图像)并等待上下文菜单出现。
  3. 用户选择 "Share..." 项。
  4. 用户在底部出现的共享菜单中选择我的应用程序扩展。
  5. 所选内容和网页URL已通过 HTT 调用共享到远程服务器。

我试过的

我通过 Xcode 进行了分享扩展。这是我的 info.plist:

NSExtension 部分
<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>

这是 test.js 文件:

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

我期望得到以下结果:在 viewDidLoad 方法中 extensionContext?.inputItems 会为我提供几个输入项,通过它们我将能够获取选定的内容和网络 URL .

哪里出了问题

viewDidLoad 方法中 extensionContext?.inputItems 只为我提供了一项——所选内容的纯文本表示(即使我同时选择了图像和文本)。我可以接受纯文本,但我需要网页 URL。

我的问题

在 iOS Safari 中使用共享扩展通过上下文菜单共享所选内容时,如何获取打开网页的 URL?

Swift 3

尝试以下方法:

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" 可以替换为从 MobileCoreServices

导入的 kUTTypeURL 字符串

我花了一个下午令人尴尬的大部分时间阅读有关此的文档并尝试了不同的扩展排列,因为我正在寻找(我认为)您正在尝试做的事情。

我得出结论,无法在 iOS 上实现此确切流程。如果用户 select 发送文本并使用上下文菜单(即 "Copy"、"Look Up"、"Share"...),您的扩展将唯一收到的是 NSItemProvider 与他们 select 编辑的文本,即不是带有预处理结果的 plist javascript。当他们从该菜单 select 共享时,当且仅当您在扩展程序的 Info.plist 文件中将 NSExtensionActivationSupportsText 设置为 YES 时,该扩展程序才会显示。

为了 运行 预处理 javascript,扩展必须根据 docsNSExtensionActivationSupportsWebPageWithMaxCount 设置为大于 0 的值。如果通过 selected 文本上下文菜单调用扩展,则该 javascript 文件永远不会 运行s。

但是,有可能非常接近所需的流程。如果用户在 Safari 中 select 一些文本,然后点击 Safari 底部的共享图标 UI 而不是点击上下文菜单中的 "Share",然后NSItemProvider 作为 plist 返回,NSExtensionJavaScriptPreprocessingFile 得到 运行。我的 javascript 文件如下所示:

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

这意味着返回给扩展的 plist 对象同时具有页面的 URL 和 selectedText。

如果扩展的唯一目的是共享 URL,而没有 URL 的纯文本不是一个合理的用例,您可能不应该 NSExtensionActivationSupportsText设置为 YES。例如,像 Pocket 这样的应用程序启用了它,但是如果用户 select 在 Safari 中输入一些文本,然后尝试通过上下文菜单共享,Pocket 不能只使用纯文本而没有页面 select 做任何有意义的事情 URL,所以它只是弹出一个非常神秘的错误消息。

我也published the code for my extension了,你想看吗