Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to cast UIImage in swift iOS 8 Extension

I have a strange problem, I am trying to build an action extension that will scan barcode from the image provided. Here is the code.

override func viewDidLoad() {
    super.viewDidLoad()

    // Get the item[s] we're handling from the extension context.

    // For example, look for an image and place it into an image view.
    // Replace this with something appropriate for the type[s] your extension supports.
    var imageFound = false
    for item: AnyObject in self.extensionContext!.inputItems {
        let inputItem = item as NSExtensionItem
        for provider: AnyObject in inputItem.attachments! {
            let itemProvider = provider as NSItemProvider
            if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as NSString) {
                // This is an image. We'll load it, then place it in our image view.
                weak var weakImageView = self.imageView
                itemProvider.loadItemForTypeIdentifier(kUTTypeImage as NSString, options: nil, completionHandler: { (image, error) in
                    if image != nil {
                        dispatch_async(dispatch_get_main_queue(),{
                            if let imageView = weakImageView {
                                var imageToSet: UIImage? = image as? UIImage
                                imageView.image = image as? UIImage
                            }

                            self.imageToScan = self.imageView.image
                            self.scanFromImage(self.imageToScan!)
                        })
                    }
                })

                imageFound = true
                break
            }
        }

        if (imageFound) {
            // We only handle one image, so stop looking for more.
            break
        }
    }
}

Now, whenever I try to get UIImage I always get nil, whereas in the image I can see an image is received. But when I try to get UIImage from that image it always returns nil. Here is the screen shot from debugging that might help

imageToSetConsoleThe complete shot

Update: Here is the description of the image that is received as :

Printing description of image: (NSSecureCoding!) image = (instance_type = Builtin.RawPointer = 0x15d674c0 -> 0x32b6be5c (void *)0x32b6be70: NSURL)

I have created the same extension using objective C and it works, but not in swift. Here is objective C Code:

- (void)viewDidLoad {
[super viewDidLoad];

// Get the item[s] we're handling from the extension context.

// For example, look for an image and place it into an image view.
// Replace this with something appropriate for the type[s] your extension supports.
BOOL imageFound = NO;
for (NSExtensionItem *item in self.extensionContext.inputItems) {
    for (NSItemProvider *itemProvider in item.attachments) {
        if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]) {
            // This is an image. We'll load it, then place it in our image view.
            __weak UIImageView *imageView = self.imageView;
            [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *image, NSError *error) {
                if(image) {
                     dispatch_async(dispatch_get_main_queue(), ^{
                        [imageView setImage:image];
                        imageToScan = image;
                        [self scanImage:imageToScan];
                    });
                }
            }];

            imageFound = YES;
            break;
        }
    }

    if (imageFound) {
        // We only handle one image, so stop looking for more.
        break;
    }
}

}

I tries to search a lot on Google but found nothing. I even tried a changed code but doe not work, here is the changed code:

                    itemProvider.loadItemForTypeIdentifier(kUTTypeImage as NSString, options: nil, completionHandler: { (image, error) in
                    if image != nil {
                        NSOperationQueue.mainQueue().addOperationWithBlock {
                            if let imageView = weakImageView {
                                var imageToSet: UIImage? = image as? UIImage
                                imageView.image = image as? UIImage
                            }

                            self.imageToScan = self.imageView.image
                            self.scanFromImage(self.imageToScan)
                        }
                    }
                })

Update: I have noticed one thing; if I create a new project and add an action extension to it, the same code is auto generated except few line that I added in the block. In that also without even changing a single line of auto generated code, the imageView.image is nil. Is this a bug in swift?? Or some bug with my Xcode app.

like image 310
Sharon Nathaniel Avatar asked Sep 17 '14 09:09

Sharon Nathaniel


2 Answers

the thing is that image is not UIImage, it's NSURL.

Change code to this one:

imageView.image = UIImage(data: NSData(contentsOfURL: image as NSURL)!)!
like image 115
d.lebedev Avatar answered Nov 17 '22 14:11

d.lebedev


U need to do like this

    if let strongImageView = weakImageView {

                   if let imageURL = image as? NSURL{

                 strongImageView.image = UIImage(data:NSData(contentsOfURL: imageURL)!)

                    }else{

                      strongImageView.image = image as? UIImage
                    }

                }

For Clarification I added Full Code Please refer, It worked for me

override func viewDidLoad() {
super.viewDidLoad()


// Get the item[s] we're handling from the extension context.

// For example, look for an image and place it into an image view.
// Replace this with something appropriate for the type[s] your extension supports.
var imageFound = false
for item: AnyObject in self.extensionContext!.inputItems {
    let inputItem = item as! NSExtensionItem
    for provider: AnyObject in inputItem.attachments! {
        let itemProvider = provider as! NSItemProvider
        if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
            // This is an image. We'll load it, then place it in our image view.
            weak var weakImageView = self.imageView
            itemProvider.loadItemForTypeIdentifier(kUTTypeImage as String, options: nil, completionHandler: { (image, error) in
                NSOperationQueue.mainQueue().addOperationWithBlock {


                if let strongImageView = weakImageView {

                       if let imageURL = image as? NSURL{

                     strongImageView.image = UIImage(data:NSData(contentsOfURL: imageURL)!)

                        }else{

                          strongImageView.image = image as? UIImage
                        }

                    }


                }
            })

            imageFound = true
            break
        }
    }

    if (imageFound) {
        // We only handle one image, so stop looking for more.
        break
    }
}
}
like image 45
Sanju Avatar answered Nov 17 '22 15:11

Sanju