问题
Works for Safari, Doesn't work for Chrome
Maybe the question is simple and stupid but I am new to iOS Development and I cannot find any right solution to solve this issue.
I need to get:
1) page url
2) page name
Extension
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>
I've added more to Chrome but it still does not work. For Safari, this is enough:
NSExtensionActivationSupportsWebPageWithMaxCount, NSExtensionActivationSupportsWebURLWithMaxCount, NSExrensionActivationSupportsText, NSExtensionJavaScriptPreprocessingFile
I try three approaches, with and without DemoPreprocessor.js. But all don't work for 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;
回答1:
In my app I've made it work, however it was some time ago and I don't remember which exact steps are necessary, so I'll post my setup in hopes it will serve as a drop in solution.
The first issue I see in your plist is a 0 count for WebURLs.
This is a part of my extension's .plist. I think that allowing arbitrary loads has nothing to do with sharing and it was needed for accessing my server, nevertheless I'll put it here for reference.
<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>
My controller's part of code responsible for getting a 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()
}
}
}
As for getting the site's name, well there are a few ways I think. One is to use the JS script that you already have in your project, another is to see whether the provider has an item with a text type (containing the site's name) but they are browser specific (some work only for Safari, some for browsers like Chrome). I chose to go about it in a different way, I use a fake WKWebView (which is never added to view hierarchy, it's just a property) and make a request with the url that I got from the provider. Then I'm able to intercept the site's name from it's JS code like so:
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
}
}
}
回答2:
Add NSExtensionActivationSupportsText and NSExtensionActivationSupportsWebPageWithMaxCount under NSExtensionActivationRule with the type as Number and set them to 1.
That was what did it for me.
来源:https://stackoverflow.com/questions/38637484/ios-share-extension-is-not-working-in-chrome