17

我想要的是

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

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

我试过的

我通过 Xcode 做了一个 Share 扩展。这是NSExtension我的部分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>

这是test.js文件:

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

我期望得到以下结果:inviewDidLoad方法extensionContext?.inputItems会为我提供几个输入项,通过这些输入项我将能够获取所选内容和 Web URL。

出了什么问题

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

我的问题

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

4

2 回答 2

14

斯威夫特 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"可以替换为kUTTypeURL从导入的字符串MobileCoreServices

于 2017-05-31T12:38:11.077 回答
6

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

我得出的结论是,这种确切的流程无法在 iOS 上实现。如果用户选择文本并使用上下文菜单(即“复制”、“查找”、“共享”...),您的扩展程序将收到的唯一NSItemProvider内容是他们选择的文本,即不是 plist带有预处理 javascript 的结果。当他们从该菜单中选择共享时,当且仅当您在扩展程序的文件中NSExtensionActivationSupportsText设置为时,扩展程序才会显示。YESInfo.plist

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

但是,有可能非常接近所需的流量。如果用户在 Safari 中,并选择了一些文本,然后,而不是点击上下文菜单中的“共享”,点击 Safari UI 底部的“共享”图标,然后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 这样的应用程序启用了它,但是如果用户在 Safari 中选择了一些文本,然后尝试通过上下文菜单进行共享,Pocket 无法仅使用纯文本而没有页面 URL 做任何有意义的事情,所以它只会弹出一个非常神秘的错误信息。

如果你想看看,我也发布了我的扩展代码。

于 2017-11-27T19:55:27.160 回答