Isuru
Isuru

Reputation: 31323

-[UIImage length]: unrecognized selector sent to instance error with a NSMutableArray with Images

I have a storyboard app which has a UIViewController and a UICollectionViewController. In the view controller, the user chooses multiple photos from the iPhone's photo library (Since there is no API for multi-select in iOS, I used ELCImagePickerController to achieve this). And it segues to the collection view controller where the selected photos should be shown in little image views.

The image library shows up and I am able to select multiple photos. But when it segues to the collection view controller, it throws the -[UIImage length]: unrecognized selector sent to instance error in the collection view's cellForItemAtIndexPath event.

Below is the code I have so far.

ViewController.h

#import <UIKit/UIKit.h>
#import "ELCImagePickerController.h"
#import "ELCAlbumPickerController.h"
#import "ELCAssetTablePicker.h"
#import "GalleryViewController.h"

@interface ViewController : UIViewController

@property (strong, nonatomic) NSMutableArray *cameraImages;

- (IBAction)chooseImages:(id)sender;

@end

ViewController.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (IBAction)chooseImages:(id)sender
{
    UIActionSheet *photoSourcePicker = [[UIActionSheet alloc] initWithTitle:nil
                                                                   delegate:self
                                                          cancelButtonTitle:@"Cancel"
                                                     destructiveButtonTitle:nil
                                                          otherButtonTitles:@"Take Photo", @"Choose from Library", nil, nil];
    [photoSourcePicker showInView:self.view];
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    switch (buttonIndex) {
        case 0:
            if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
                ELCAlbumPickerController *albumController = [[ELCAlbumPickerController alloc] initWithNibName:nil bundle:nil];
                ELCImagePickerController *elcPicker = [[ELCImagePickerController alloc] initWithRootViewController:albumController];
                albumController.parent = elcPicker;
                elcPicker.delegate = self;

                if ([self.view respondsToSelector:@selector(presentViewController:animated:completion:)]){
                    [self presentViewController:elcPicker animated:YES completion:nil];
                } else {
                    [self presentViewController:elcPicker animated:YES completion:nil];
                }
            }
            else {
                UIAlertView *alert;
                alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                   message:@"This device doesn't have a camera"
                                                  delegate:self
                                         cancelButtonTitle:@"Ok"
                                         otherButtonTitles:nil, nil];
                [alert show];
            }
            break;

        case 1:
            if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
                ELCAlbumPickerController *albumController = [[ELCAlbumPickerController alloc] initWithNibName:nil bundle:nil];
                ELCImagePickerController *elcPicker = [[ELCImagePickerController alloc] initWithRootViewController:albumController];
                albumController.parent = elcPicker;
                elcPicker.delegate = self;

                if ([self.view respondsToSelector:@selector(presentViewController:animated:completion:)]){
                    [self presentViewController:elcPicker animated:YES completion:nil];
                } else {
                    [self presentViewController:elcPicker animated:YES completion:nil];
                }
            }
            else {
                UIAlertView *alert;
                alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                   message:@"This device doesn't support photo libraries"
                                                  delegate:self
                                         cancelButtonTitle:@"Ok"
                                         otherButtonTitles:nil, nil];
                [alert show];
            }
            break;
    }
}

- (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info
{
    [self dismissViewControllerAnimated:YES completion:nil];

    self.cameraImages = [[NSMutableArray alloc] initWithCapacity:info.count];


    for (NSDictionary *camImage in info) {
        UIImage *image = [camImage objectForKey:UIImagePickerControllerOriginalImage];
        [self.cameraImages addObject:image];
    }
    /*
     for (UIImage *image in info) {
     [self.attachImages addObject:image];
     }
     */

    NSLog(@"number of images = %d", self.cameraImages.count);
    if (self.cameraImages.count > 0) {
        [self performSegueWithIdentifier:@"toGallery" sender:nil];
    }
}


- (void)elcImagePickerControllerDidCancel:(ELCImagePickerController *)picker
{
    if ([self respondsToSelector:@selector(dismissViewControllerAnimated:completion:)]) {
        [self dismissViewControllerAnimated:YES completion:nil];
    } else {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"toGallery"]) {
        GalleryViewController *galleryVC = [segue destinationViewController];
        galleryVC.selectedImages = self.cameraImages;
    }
}

@end

GalleryViewController.h

#import <UIKit/UIKit.h>
#import "ELCImagePickerController.h"
#import "ELCAlbumPickerController.h"
#import "ELCAssetTablePicker.h"
#import "ImageCell.h"

@interface GalleryViewController : UICollectionViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource>

@property (strong, nonatomic) NSMutableArray *selectedImages;

@end

GalleryViewController.m

#import "GalleryViewController.h"

@interface GalleryViewController ()

@end

@implementation GalleryViewController


- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}


- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.selectedImages.count;
}


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"imgCell" forIndexPath:indexPath];
    UIImage *image;
    int row = indexPath.row;

    image = [UIImage imageNamed:self.selectedImages[row]]; //This is where it throws the error
    cell.imageView.image = image;

    return cell;
}

@end

To further demonstrate the issue, I've slapped together a demo project which you can download from here.

I know thus question has been asked many time before here on SO. I tried them all but to no avail prior to posting my question here.

I'd appreciate if someone can tell me how to get rid of this error.

Thank you.

Upvotes: 4

Views: 7337

Answers (2)

Satheesh
Satheesh

Reputation: 11276

Hey I understood your problem you are already having an array of images, why using imageNamed: constructor again.

image = [UIImage imageNamed:self.selectedImages[row]];
cell.imageView.image = image;
//This throws a exception because, you have UIImage objects in your array and here imageNamed: takes NSString as an argument , so you are trying to pass a UIImage object instead of a NSString object

Directly take out image from array and assign like this:

cell.imageView.image = (UIImage*) [self.selectedImages objectAtIndex:row];

UIImage * is probably not needed.

Upvotes: 13

user2197398
user2197398

Reputation:

self.selectedImages[row] should be a NSString. It seems like it is a UIImage instead of an NSString. Its trying to call length method on the UIImage instance.

Upvotes: 1

Related Questions