8

I'm working on an iOS app that uses a photo share extension, where the image is processed and our main function is triggered.

In the simulator on the Photo's app, this works great. I decided to run on the device from the Photo's app and it also works great, but when I screenshot and try to share from iOS 11's new "Quick screenshot" the extension crashes, any ideas?

The extension takes an image, sends it to the server, gets a response and displays that response (all in the extension). This annoys me as Messenger and Snapchat share extensions still work when accessed from a quick screenshot!!

Xcode 9 also isn't giving me any logs from the share extension. it's also worth noting that I'm using a developer account that I need to "trust" each time I reinstall the app on the device.

Code:

// App Group keys

let suiteName = "group.suite.id"

override func viewDidLoad() {
    print("Styling views..")
    styleViews()
    print("Styled views")
    print("Adding notifications..")
    addNotifications()
    print("Added notifications")
    print("Fetching image..")
    fetchSharedImage()
}

func styleViews(){
    // Set up main view
    mainView.layer.cornerRadius = 8
    mainShadowView.addShadow()

    // Set up views and buttons
    // Code hidden, applies shadows etc.

    // Code hidden, moves constraints of a view
}

func addNotifications(){
    // Helps views tell their parent (this view controller) to navigate to another form
    NotificationCenter.default.addObserver(forName: NotificationDisplayFetchedLink, object: nil, queue: nil){ notification in
        // Handles user info in lambda block
        guard let userInfo = notification.userInfo,
            let link = userInfo["link"] as? String
            else {
                print("No userInfo found in notification")
                return
            }
        self.displayResult(with: link)
    }
}

func fetchSharedImage(){
    // Make sure we have a valid extension item
    if let content = extensionContext!.inputItems[0] as? NSExtensionItem {
        let contentType = kUTTypeImage as String

        // Verify the provider is valid
        if let contents = content.attachments as? [NSItemProvider] {
            // look for images
            for attachment in contents {
                if attachment.hasItemConformingToTypeIdentifier(contentType) {
                    attachment.loadItem(forTypeIdentifier: contentType, options: nil) { data, error in
                        let url = data as! URL
                        if let imageData = try? Data(contentsOf: url) {
                            self.selectedImage = UIImage(data: imageData)

                            DispatchQueue.main.async {
                                self.selectedImageView.layer.cornerRadius = 8
                                self.selectedImageView.image = self.selectedImage
                            }
                            self.makeWebRequest()

                        }
                    }
                }
            }
        }
    }
}

func makeWebRequest(){
    let url = URL(string: "url.json")
    let task = URLSession.shared.dataTask(with: url!) { data, response, error in
        guard error == nil else {
            return
        }
        guard let data = data else {
            // Data is empty
            return
        }

        let json = try! JSONSerialization.jsonObject(with: data, options: []) as! NSDictionary
        guard let dict = json as? [String:Any] else { return }
        let item = dict["item"]
        guard let itemData = item as? [[String:Any]] else { return }
        let link = itemData[0]["url"]
        NotificationCenter.default.post(name: NotificationDisplayFetchedLink, object: nil, userInfo: [link: link!])
    }
    task.resume()
}

Edit:

So the solution (as Owen Zhao has said) is that the iOS 11 screenshot editor returns a UIImage, while apps like Photos would return URL.

My solution to handling this elegantly was saving the UIImage OR the URL cast to a UIImage to the iOS temporary directory (deleted after 3 days) and then returning the URL of the image in that directory to the share extension.

Kiran Sarvaiya
  • 1,318
  • 1
  • 13
  • 37
bluey31
  • 180
  • 3
  • 14
  • 1
    Please share your code you've tried – Krunal Jun 12 '17 at 12:13
  • Updated to show code that powers the extension.. – bluey31 Jun 12 '17 at 12:21
  • 1
    Can you share error line.. If it's not printing any error message in console, then use debug mode and provide an error line (it may be in makeWebRequest() method) – Krunal Jun 12 '17 at 12:25
  • Xcode won't show error logs for the Share Extension when it's running on my device, only for the app I'm sharing from, which is weird as it would when running on simulator. It might be worth mentioning the developer id is "untrusted" (personal account) – bluey31 Jun 12 '17 at 12:29
  • The obvious question is if this is because we're talking beta. So yes, does this work with Xcode 8 and iOS 10? Seriously, we're one week beyond Beta 1.... maybe you need to file a bug? –  Jun 12 '17 at 16:33

2 Answers2

8

let url = data as! URL if let imageData = try? Data(contentsOf: url) {

The issue is because the data here is not a URL. It is a "public.image", try to convert to UIImage instead of Data.

Owen Zhao
  • 3,205
  • 1
  • 26
  • 43
0

In Objective C You can use following code for image that shared as screen shot. Screen shot having .png extension so use public.png instead of public.jpeg

if ([itemProvider hasItemConformingToTypeIdentifier:@"public.png"]){
            [itemProvider loadItemForTypeIdentifier:@"public.png" options:nil completionHandler: ^(id<NSSecureCoding> item, NSError *error) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSData *imgData;
                    if([(NSObject*)item isKindOfClass:[NSURL class]]) {
                        imgData = [NSData dataWithContentsOfURL:(NSURL*)item];
                    }
                    if([(NSObject*)item isKindOfClass:[UIImage class]]) {
                        imgData = UIImagePNGRepresentation((UIImage*)item);
                    }
 UIImage *image=[UIImage imageWithData:imgData];
});

            }];
Yogesh Dalavi
  • 73
  • 4
  • 15