iOS分享扩展在Chrome中无法工作

11

适用于Safari,但不适用于Chrome

也许这个问题很简单愚蠢,但我是iOS开发的新手,找不到任何正确的解决方案来解决这个问题。

我需要获取:
1)页面网址
2)页面名称

扩展

Info.plist

<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionActivationRule</key>
        <dict>
            <key>NSExrensionActivationSupportsText</key>
            <true/>
            <key>NSExtensionActivationSupportsFileWithMaxCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsImageWithMaxCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsMovieWithMaxCount</key>
            <integer>20</integer>
            <key>NSExtensionActivationSupportsWebPageWithMaxCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
            <integer>0</integer>
        </dict>
        <key>NSExtensionJavaScriptPreprocessingFile</key>
        <string>DemoPreprocessor</string>
    </dict>
    <key>NSExtensionMainStoryboard</key>
    <string>MainInterface</string>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.share-services</string>
</dict>

我已经在Chrome上添加了更多内容,但它仍无法正常工作。对于Safari,这已经足够了:

NSExtensionActivationSupportsWebPageWithMaxCount, NSExtensionActivationSupportsWebURLWithMaxCount, NSExrensionActivationSupportsText, NSExtensionJavaScriptPreprocessingFile

我尝试了三种方法,带有和不带有。但都无法在Chrome中正常工作:

1. ShareViewController.swift

override func viewDidLoad() {
    super.viewDidLoad()

    let items = extensionContext?.inputItems
    var itemProvider: NSItemProvider?

    if items != nil && items!.isEmpty == false {
        let item = items![0] as! NSExtensionItem
        if let attachments = item.attachments {
            if !attachments.isEmpty {
                itemProvider = (attachments[0] as? NSItemProvider)!
            }
        }
    }

    let urlType = kUTTypePropertyList as String
    if ((itemProvider?.hasItemConformingToTypeIdentifier(urlType)) != nil) {
        itemProvider?.loadItemForTypeIdentifier(urlType, options: nil, completionHandler: {
            (item: NSSecureCoding?, error: NSError!) -> Void in
            if let resultDict = item as? NSDictionary {
                self.linkName = resultDict[NSExtensionJavaScriptPreprocessingResultsKey]!["URL"] as! String
                self.linkUrl = resultDict[NSExtensionJavaScriptPreprocessingResultsKey]!["title"] as! String
            }

        })
    }

}

2 ShareViewController.swift

override func viewDidLoad() {
    super.viewDidLoad()

    let items = extensionContext?.inputItems
    var itemProvider: NSItemProvider?

    if items != nil && items!.isEmpty == false {
        let item = items![0] as! NSExtensionItem
        if let attachments = item.attachments {
            if !attachments.isEmpty {
                itemProvider = (attachments[0] as? NSItemProvider)!
            }
        }
    }

    let urlType = kUTTypeURL as NSString as String

    if ((itemProvider?.hasItemConformingToTypeIdentifier(urlType)) != nil) {
       itemProvider?.loadItemForTypeIdentifier(urlType, options: nil, completionHandler: {
           item, error in
           self.linkName = self.contentText
           self.linkUrl = "\(item!)"
       })
    }

}

3 ShareViewController.swift

override func viewDidLoad() {
    super.viewDidLoad()

    let items = extensionContext?.inputItems
    var itemProvider: NSItemProvider?

    if items != nil && items!.isEmpty == false {
        let item = items![0] as! NSExtensionItem
        if let attachments = item.attachments {
            if !attachments.isEmpty {
                itemProvider = (attachments[0] as? NSItemProvider)!
            }
        }
    }

    if self.linkUrl.characters.count < 1 {
        if ((itemProvider?.hasItemConformingToTypeIdentifier("public.url")) != nil) {
            itemProvider?.loadItemForTypeIdentifier("public.url", options: nil, completionHandler: {
                item, error in self.linkUrl = "\(item!)"
            })
        }
    }

}

DemoPreprocessor.js

var MyPreprocessor = function() {};

MyPreprocessor.prototype = {
    run: function(arguments) {
        arguments.completionFunction({"URL": document.URL, "pageSource": document.documentElement.outerHTML, "title": document.title, "selection": window.getSelection().toString()});
    }
};

var ExtensionPreprocessingJS = new MyPreprocessor;

@EricD 我需要删除 Swift 标签吗? - Denis
@EricD 我认为 plist - manifest、ShareViewController.swift 和 DemoPreprocessor.js 是相关的,因为我阅读了一些文档、问题、答案和人们在那里写道,有些组合是有效的(使用 PreprocessingJS,有些不使用,使用不同的 NSExtensionActivationRule)。但是我尝试的所有内容都只在 Safari 中工作,在 Chrome 中无法工作。 - Denis
2个回答

5

我在我的应用中已经让它工作了,不过那是一段时间之前的事情了,我不记得需要哪些确切步骤,因此我将发布我的设置,希望它能作为一个快速解决方案。

我在你提供的plist中看到的第一个问题是WebURL的计数为0。

这是我的扩展.plist的一部分。我认为允许任意加载与共享无关,并且需要访问我的服务器,但我会将其放在这里供参考。

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionActivationRule</key>
        <dict>
            <key>NSExtensionActivationSupportsImageWithMaxCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
            <integer>1</integer>
        </dict>
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.share-services</string>
    <key>NSExtensionPrincipalClass</key>
    <string>ShareViewController</string>
</dict>

我的控制器代码负责获取URL:

// MARK: - NSExtensionRequestHandling
extension ShareViewController {
    override func beginRequestWithExtensionContext(context: NSExtensionContext) {
        super.beginRequestWithExtensionContext(context)

        guard let provider = (context.inputItems.first?.attachments as? [NSItemProvider])?.first else { return cancel() }

        if provider.hasItemConformingToTypeIdentifier(kUTTypeURL as String) {
            provider.loadItemForTypeIdentifier(kUTTypeURL as String, options: nil) { url, error in
                guard let url = url as? NSURL else { return self.cancel() }
                // do what you want with the url
            }
        } else {
            cancel()
        }
    }
}

关于获取网站名称,我认为有几种方法。一种是使用你项目中已经有的JS脚本,另一种是查看提供商是否有一个包含网站名称的文本类型项,但它们是特定于浏览器的(有些仅适用于Safari,有些适用于诸如Chrome之类的浏览器)。我选择了另一种方法,我使用一个虚假的WKWebView(它从未添加到视图层次结构,只是一个属性),并使用我从提供商那里得到的URL进行请求。然后,我能够从网站的JS代码中截取出网站的名称,就像这样:

func setupHiddenWebView() {
    hiddenWebView = WKWebView()
    hiddenWebView?.navigationDelegate = self
}

func setupForURL(url: NSURL) {
    (...)
    hiddenWebView?.loadRequest(NSURLRequest(URL: url))
}

// MARK: - WKNavigationDelegate
extension ShareView: WKNavigationDelegate {
    func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
        webView.evaluateJavaScript("document.title") { result, error in
            guard let title = result as? String else { return }
            // do what you want with the page's title
        }
    }
}

你能澄清一下这段代码吗?hiddenWebview没有声明,(...)不清楚,而且也不清楚你为什么要使用扩展,以及你正在扩展什么,出于什么原因。谢谢! - lucius degeer

0
在 NSExtensionActivationRule 下添加 NSExtensionActivationSupportsText 和 NSExtensionActivationSupportsWebPageWithMaxCount,类型为 Number,并将它们设置为 1。
这就是解决问题的方法。

NSExtensionActivationSupportsText 应该被设置为布尔类型 <true/> 而不是数字。 - Albert Vila Calvo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接