iOS共享扩展程序:通过Safari

时间:2017-05-27 15:47:46

标签: ios swift ios8-share-extension share-extension

我想要什么

我试图实现以下用户流程:

  1. 用户正在iOS Safari中浏览网页。
  2. 用户选择一些内容(文本和图像)并等待上下文菜单出现。
  3. 用户选择"分享..."项目
  4. 用户从底部显示的共享菜单中选择我的应用扩展程序。
  5. 选定的内容和网页URL通过HTT呼叫共享给远程服务器。
  6. 我尝试了什么

    我通过Xcode进行了分享扩展。这是NSExtension的{​​{1}}部分:

    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; 方法viewDidLoad会为我提供几个输入项,通过这些输入项,我可以获取所选内容和网址。

    出了什么问题

    extensionContext?.inputItems方法viewDidLoad中,我只提供了一个项目 - 所选内容的纯文本表示(即使我同时选择了图片和文字)。我可以使用纯文本,但我需要网页网址。

    我的问题

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

2 个答案:

答案 0 :(得分:5)

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

导入的MobileCoreServices字符串

答案 1 :(得分:1)

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

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

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

然而,可能会非常接近到所需的流量。如果用户在Safari中,并选择一些文本,然后,而不是点击&#34;分享&#34;在上下文菜单中,点击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。

如果扩展程序的唯一目的是共享网址,而没有网址的纯文本不是一个敏感的用例,则可能不应将NSExtensionActivationSupportsText设置为YES。例如,像Pocket这样的应用程序启用了它,但是如果用户在Safari中选择了一些文本,然后尝试通过上下文菜单进行共享,那么Pocket只能通过明文而不是页面URL做任何有意义的事情,所以它只是弹出一个非常神秘的错误信息。

如果你想看看,我也会published the code for my extension