iosswiftios-sharesheet

App Extension Swift: get url from any app without javascript


i would like to get the url via an action extension in every app, not just safari. For example in twitter.app when you long press a link the share sheets opens and extensions can use the url. If possible i would like to do it without the javascript file.

Currently i am using a js file to get the url in safari and this works, but in other apps like twitter only a black screen appears.

    let extensionItem = extensionContext?.inputItems.first as! NSExtensionItem
    let itemProvider = extensionItem.attachments?.first as! NSItemProvider

    let propertyList = String(kUTTypePropertyList)
    if itemProvider.hasItemConformingToTypeIdentifier(propertyList) {
        itemProvider.loadItemForTypeIdentifier(propertyList, options: nil, completionHandler: { (item, error) -> Void in
            let dictionary = item as! NSDictionary
            NSOperationQueue.mainQueue().addOperationWithBlock {
                let results = dictionary[NSExtensionJavaScriptPreprocessingResultsKey] as! NSDictionary
                let urlString = results["currentUrl"] as? String
                self.url = NSURL(string: urlString!)

                print(self.url)
            }
        })
    } else {
        print("error")
    }

I would like to get the url through the share sheet in every app without the need for a javascript file.

thanks in advance


Solution

  • If all you need is the URL, get rid of the JS preprocessing file as it seems to replace all other extension item attachments with the property list.

    Remove NSExtensionJavaScriptPreprocessingFile in your Info.plist. It should look like this:

    <key>NSExtensionAttributes</key>
        <dict>
            <key>NSExtensionActivationRule</key>
            <dict>
                <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
                <string>1</string>
            </dict>
        </dict>
    

    Then, instead of asking your itemProvider for a property list, simply do this:

    if itemProvider.hasItemConformingToTypeIdentifier("public.url") {
         itemProvider.loadItemForTypeIdentifier(kUTTypeURL as String, options: nil, completionHandler: { (result: NSSecureCoding?, error: NSError!) in
              let url = result as? NSURL
              //assign url here
          })
     }
    

    If you need any additional information that you were only getting from the JS preprocessing (perhaps a title), you can load the url in a UIWebview and use:

    let title = webView.stringByEvaluatingJavaScriptFromString("document.title")
    

    This will work with Twitter, but I have not confirmed on any additional apps. Of course, keep in mind that many of the links that are selectable on Twitter are links to Tweets and Twitter user pages, not the actual posted content.