13

I'm trying to create an iOS share extension in swift. When the user is in safari and opens the share extension, I want to be able to grab the URL and use it in my app. I know I can put the code below in the didSelectPost() function in the ShareViewController to get the text that the user enters in the share extension, but how do I get the URL of the web page the user is on when they click the share extension? I'm fairly new to iOS extensions, so any help would be much appreciated.

 let shareDefaults = NSUserDefaults(suiteName: "groupName")
 shareDefaults?.setObject(self.contentText, forKey: "stringKey")
 shareDefaults?.synchronize()
xyz123
  • 191
  • 1
  • 3
  • 6

2 Answers2

26

This is how you get the URL:

- (void)didSelectPost {
    NSExtensionItem *item = self.extensionContext.inputItems.firstObject;
    NSItemProvider *itemProvider = item.attachments.firstObject;
    if ([itemProvider hasItemConformingToTypeIdentifier:@"public.url"]) {
        [itemProvider loadItemForTypeIdentifier:@"public.url"
                                        options:nil
                              completionHandler:^(NSURL *url, NSError *error) {
                                  NSString *urlString = url.absoluteString;
                                  // send url to server to share the link
                                  [self.extensionContext completeRequestReturningItems:@[]         
                                                                     completionHandler:nil];
                              }];
    }
}

Or in Swift:

override func didSelectPost() {
    if let item = extensionContext?.inputItems.first as? NSExtensionItem {
        if let itemProvider = item.attachments?.first as? NSItemProvider {
            if itemProvider.hasItemConformingToTypeIdentifier("public.url") {
                itemProvider.loadItemForTypeIdentifier("public.url", options: nil, completionHandler: { (url, error) -> Void in
                    if let shareURL = url as? NSURL {
                        // send url to server to share the link
                    }
                    self.extensionContext?.completeRequestReturningItems([], completionHandler:nil)
                })
            }
        }
    }
}
joern
  • 27,354
  • 7
  • 90
  • 105
  • Works perfectly! (why wasn't this marked as the right answer?) – Sirab33 Apr 06 '16 at 00:11
  • Hi Thank you for this, it works at my side. One more help can you do for me,i need to inject the username and password into webpage using my extention , how can i inject those for autofill functionality ? – Anita Nagori Jan 19 '18 at 06:47
  • @Anita Thanks for your comment. Please open a new question for the injection issue. It needs more details and the comments aren't the right place for this ;-) – joern Jan 19 '18 at 10:05
17

There is one small change to this. In Chrome the public.url is in item 1, not item 0 of the attachements. Looping through to find it is better and will work on both chrome and safari.

if let item = extensionContext?.inputItems.first as? NSExtensionItem {
    if let attachments = item.attachments as? [NSItemProvider] {
        for attachment: NSItemProvider in attachments {
            if attachment.hasItemConformingToTypeIdentifier("public.url") {
                attachment.loadItemForTypeIdentifier("public.url", options: nil, completionHandler: { (url, error) in
                    if let shareURL = url as? NSURL {
                        // Do stuff with your URL now. 
                    }
                    self.extensionContext?.completeRequestReturningItems([], completionHandler:nil)
                })
            }
        }
    }
}
Sam Napolitano
  • 171
  • 1
  • 3
  • This is EXACTLY what I have spent a day learning and have found your post within seconds of learning it myself, the hard way! – Nick Jul 04 '17 at 16:18
  • 2
    Should the attachment in the above example contain a com.apple.property-list? I can't seem o figure this one out. Using the code above I am not getting the URL. The completionHandler doesn't get executed because there doesn't seem to be a "public.url" in the com.apple.property-list – boywithaxe Aug 22 '17 at 18:57
  • Beautiful, just beautiful –  May 12 '19 at 03:47
  • If you're having trouble getting your completion block to run, try replacing "loadItem" with "loadItemAsync" – Russ J Oct 05 '19 at 15:10
  • hi, if i need to handle image and video, so do i called loadItemForTypeIdentifier for 2 times? – famfamfam Mar 27 '21 at 11:45