3

I have a working share extension written in swift. When I test a share operation from Safari, I always only get the URL type (kUTTypeURL).

What I want is to get some form of rendered version of what the user is looking at (PDF or HTML?). Using the URL and opening it in a webview is not workable due to authentication issues, etc.

I've tried many different activation rules with no change. Here is the current one I am using:

            <key>NSExtensionActivationRule</key>
        <dict>
            <key>NSExtensionActivationSupportsFileWithMaxCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsImageWithMaxCount</key>
            <integer>20</integer>
            <key>NSExtensionActivationSupportsMovieWithMaxCount</key>
            <integer>0</integer>
            <key>NSExtensionActivationSupportsText</key>
            <true/>
            <key>NSExtensionActivationSupportsWebPageWithMaxCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
            <integer>1</integer>
        </dict>

My controller looks like this - when run from Safari, it always only has one attachment type - the URL:

   override func didSelectPost() {


    if let item = extensionContext?.inputItems.first as? NSExtensionItem {
        if let attachments = item.attachments {
            for attachment: NSItemProvider in attachments {
                if attachment.hasItemConformingToTypeIdentifier(kUTTypePropertyList as String) {
                    attachment.loadItem(forTypeIdentifier: kUTTypePropertyList as String, options: nil, completionHandler: { (data, error) in
                        // Do stuff with this content now
                        self.extensionContext?.completeRequest(returningItems: [], completionHandler:nil)
                    })
                }
                if attachment.hasItemConformingToTypeIdentifier(kUTTypeURL as String) {
                    attachment.loadItem(forTypeIdentifier: kUTTypeURL as String, options: nil, completionHandler: { (url, error) in
                        if let shareURL = url as? NSURL {
                            // Do stuff with your URL now.
                        }
                        self.extensionContext?.completeRequest(returningItems: [], completionHandler:nil)
                    })
                }
            }
        }
    }
}

Other approaches I've seen use a javascript file to walk the DOM but have seen no good examples and I'm not clear on if this would help me in any case.

Matt__C
  • 319
  • 2
  • 10

1 Answers1

1

The key is in using this line in your info.plist file:

    <key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionJavaScriptPreprocessingFile</key>
        <string>Action</string>
        <key>NSExtensionActivationRule</key>
        ...your should be fine...
    </dict>

At NSExtensionJavaScriptPreprocessingFile you specify the name of the .js file that contains javascript file that must contain a global object named ExtensionPreprocessingJS. You should then search for the items conforming to kUTTypePropertyList in your code (and it seems that you do already that looking at your code).

This is a short list of what you should do, ask if you need something more and it is easy to find more data on the internet if you start from this too.

Ivan Ičin
  • 9,672
  • 5
  • 36
  • 57
  • This would let me write javascript that could walk the DOM, but then it would need to be rendered into some form to match what the user is seeing. Would this all be possible in Javascript? – Matt__C Apr 02 '19 at 18:58
  • I don't quite understand your question, you can return outerHTML or innerText depending on what you need from JavaScript, so there are no limitations in achieving what you wanted. – Ivan Ičin Apr 02 '19 at 19:43
  • I'm after the rendered version of the page. i.e. What the user is looking at. Not the raw HTML. I guess that would mean using something like jsPDF but I don't think it would be a universal solution to give WYSIWYG renedering for any possible web page – Matt__C Apr 04 '19 at 13:57
  • @Matt__C could you define the "rendered version of the page" in the terms of API? I don't think that there is anything similar in iOS. This isn't the raw site HTML but the HTML parsed by the browser (with some errors in HTML fixed in that process) and it is turned into the webview without any other intermediate format that you could use. You can use some cocoapods like Kanna to convert this to some hierarchical structure if you want to. – Ivan Ičin Apr 04 '19 at 14:04
  • I simply want the share from Safari to provide what the user is seeing, not a URL. Other applications in iOS provide this, why not Safari? Getting the HTML of the page the user is seeing doesn't necessarily provide that either, depending upon how the page is rendered. If this is not possible, that's an answer too. – Matt__C Apr 05 '19 at 13:17
  • The app decides what content to share and you can't receive it if it is not shared already. So I don't see anything other than using this method, you may try JavaScript to return something else like here: https://stackoverflow.com/questions/4912092/using-html5-canvas-javascript-to-take-in-browser-screenshots/6678156#6678156 – Ivan Ičin Apr 05 '19 at 13:28