Reputation: 31323
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
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
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