Currently i have 2 view Controllers, i select a photo from view controller,A and pass the image url to second view controller,B and use the url to retrieve the image selected from A.But problem is the image can be retrieved at viewDidLoad but cannot retrieve at table viewcellForRowAtIndexPath. I not sure what is the root cause can somebody help me?
//A.m
(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// Initialize View Controller B
B *b = [[B alloc]initWithNibName:#"PhotosListViewController" bundle:nil];
// get the ref url
NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
photoListViewController.test = imageURL;
NSLog(#"%#",imageURL);
[picker dismissViewControllerAnimated:YES completion:nil];
[self.navigationController pushViewController:photoListViewController animated:YES];
}
- (IBAction)organiseAttachement:(id)sender {
// Initialize View Controller
B *b = [[PhotosListViewController alloc]initWithNibName:#"B" bundle:nil];
[self.navigationController pushViewController:b animated:YES];
}
//B.h
#import <UIKit/UIKit.h>
#interface PhotosListViewController : UITableViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
#property (nonatomic, strong) NSURL *test;
#end
//B.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Image is THIS --- %#",test);
// define the block to call when we get the asset based on the url (below)
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *imageAsset)
{
ALAssetRepresentation *imageRep = [imageAsset defaultRepresentation];
CGImageRef iref = [imageRep fullResolutionImage];
if (iref) {
self.galleryImage = [UIImage imageWithCGImage:iref];
}
[self.tableView reloadData];
NSLog(#"[imageRep filename] : %#", [imageRep filename]);
NSLog(#"[imageRep image] : %#", galleryImage);
};
// get the asset library and fetch the asset based on the ref url (pass in block above)
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
[assetslibrary assetForURL:test resultBlock:resultblock failureBlock:nil]
}
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.imageView.image = self.galleryImage;
return cell;
}
Replace
// define the block to call when we get the asset based on the url (below)
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *imageAsset)
{
ALAssetRepresentation *imageRep = [imageAsset defaultRepresentation];
CGImageRef iref = [imageRep fullResolutionImage];
if (iref) {
self.galleryImage = [UIImage imageWithCGImage:iref];
}
NSLog(#"[imageRep filename] : %#", [imageRep filename]);
NSLog(#"[imageRep image] : %#", galleryImage);
};
with
// define the block to call when we get the asset based on the url (below)
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *imageAsset)
{
ALAssetRepresentation *imageRep = [imageAsset defaultRepresentation];
CGImageRef iref = [imageRep fullResolutionImage];
if (iref) {
self.galleryImage = [UIImage imageWithCGImage:iref];
}
[self.tableView reloadData]; //Reload the tableView.
NSLog(#"[imageRep filename] : %#", [imageRep filename]);
NSLog(#"[imageRep image] : %#", galleryImage);
};
EDITED:
A.m
#interface A ()
#property(nonatomic,strong) B *b;
#end
#implementation b
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
if(self.b)
{
// Initialize View Controller B
self.b = [[B alloc]initWithNibName:#"PhotosListViewController" bundle:nil];
}
// get the ref url
NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
self.b.test = imageURL;
NSLog(#"%#",imageURL);
[picker dismissViewControllerAnimated:YES completion:nil];
[self.navigationController pushViewController:self.b animated:YES];
}
- (IBAction)organiseAttachement:(id)sender {
if(self.b == nil)
{
// Initialize View Controller
self.b = [[PhotosListViewController alloc]initWithNibName:#"B" bundle:nil];
}
[self.navigationController pushViewController:self.b animated:YES];
}
#end
Related
I use Parse.com for backend, I've two views : InboxView (where I receive images from friends), and ChatView.
When I send images, I send images with recipientIds of user (that can be multiple users) in "Messages" class (parse).
I receive images in my InboxView, I can see in cell for row the name of the friend that send images.
I would like that when I select a row (username who sends me image) that stores the PFUser objectId of the user who sends me the image, and not all of the recipientIds.
How can I make that ?
Here is my code :
Inbox.h :
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import <MediaPlayer/MediaPlayer.h>
#interface InboxViewController : UITableViewController
#property (nonatomic, strong) NSArray *messages;
#property (nonatomic, strong) PFObject *selectedMessage;
#property (nonatomic, strong) MPMoviePlayerController *moviePlayer;
#property (nonatomic, strong) UIImage *MindleNav;
- (UIImage *)resizeImage:(UIImage *)image toWidth:(float)width andHeight:(float)height;
#end
and inbox.m :
#import "InboxViewController.h"
#import "ImageViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "LoginViewController.h"
#import "FriendsViewController.h"
#interface InboxViewController ()
#end
#implementation InboxViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.MindleNav = [UIImage imageNamed:#"MindleNavItem.png"];
UIImage *newImage = [self resizeImage:self.MindleNav toWidth:150.0f andHeight:48.0f];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:newImage];
self.MindleNav = newImage;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFQuery *query = [PFQuery queryWithClassName:#"Messages"];
[query whereKey:#"recipientIds" equalTo:[[PFUser currentUser] objectId]];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
// We found messages!
self.messages = objects;
[self.tableView reloadData];
}
}];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.messages count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFObject *message = [self.messages objectAtIndex:indexPath.row];
cell.textLabel.text = [message objectForKey:#"senderName"];
NSString *fileType = [message objectForKey:#"fileType"];
if ([fileType isEqualToString:#"image"]) {
cell.imageView.image = [UIImage imageNamed:#"icon_image"];
}
else {
// cell.imageView.image = [UIImage imageNamed:#"icon_video"];
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedMessage = [self.messages objectAtIndex:indexPath.row];
NSString *fileType = [self.selectedMessage objectForKey:#"fileType"];
if ([fileType isEqualToString:#"image"]) {
[self performSegueWithIdentifier:#"showImage" sender:self];
}
else {
// File type is text
// // File type is video
// PFFile *videoFile = [self.selectedMessage objectForKey:#"file"];
// NSURL *fileUrl = [NSURL URLWithString:videoFile.url];
// self.moviePlayer.contentURL = fileUrl;
// [self.moviePlayer prepareToPlay];
// UIImage *thumbnail = [self thumbnailFromVideoAtURL:self.moviePlayer.contentURL];
//
//// [self.moviePlayer thumbnailImageAtTime:0 timeOption:MPMovieTimeOptionNearestKeyFrame];
//
// // Add it to the view controller so we can see it
// UIImageView *imageView = [[UIImageView alloc] initWithImage:thumbnail];
// [self.moviePlayer.backgroundView addSubview:imageView];
// [self.moviePlayer setFullscreen:YES animated:YES];
}
// Delete it!
NSMutableArray *recipientIds = [NSMutableArray arrayWithArray:[self.selectedMessage objectForKey:#"recipientIds"]];
NSLog(#"Recipients: %#", recipientIds);
if ([recipientIds count] == 1) {
// Last recipient - delete!
// [self.selectedMessage deleteInBackground];
}
else {
// Remove the recipient and save
// [recipientIds removeObject:[[PFUser currentUser] objectId]];
// [self.selectedMessage setObject:recipientIds forKey:#"recipientIds"];
// [self.selectedMessage saveInBackground];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showImage"]) {
[segue.destinationViewController setHidesBottomBarWhenPushed:YES];
ImageViewController *imageViewController =
(ImageViewController *)segue.destinationViewController;
imageViewController.message = self.selectedMessage;
}
}
- (UIImage *)thumbnailFromVideoAtURL:(NSURL *)url
{
AVAsset *asset = [AVAsset assetWithURL:url];
// Get thumbnail at the very start of the video
CMTime thumbnailTime = [asset duration];
thumbnailTime.value = 0;
// Get image from the video at the given time
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:thumbnailTime actualTime:NULL error:NULL];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return thumbnail;
}
- (UIImage *)resizeImage:(UIImage *)truckImage toWidth:(float)width andHeight:(float)height {
CGSize newSize = CGSizeMake(width, height);
CGRect newRectangle = CGRectMake(0, 0, width, height);
UIGraphicsBeginImageContext(newSize);
[self.MindleNav drawInRect:newRectangle];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resizedImage;
}
#end
Here's my method inside of the UITableViewDataSource view controller
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"studentCell";
StudentTableCell *cell = (StudentTableCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
// Never gets called
}
Student *student = self.studentList[indexPath.row];
cell.nameFirst.text = student.nameFirst;
cell.nameLast.text = student.portrait.assetURL;
// Portrait
CGImageRef portraitRef = [cell.portrait.image CGImage];
CIImage *portraitImage = [cell.portrait.image CIImage];
if (portraitRef == NULL && portraitImage == nil) {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:[NSURL URLWithString:student.portrait.assetURL] resultBlock:^(ALAsset *asset) {
ALAssetRepresentation *representation = [asset defaultRepresentation];
CGImageRef assetRef = [representation fullResolutionImage];
if (assetRef) {
[cell.portrait setImage:[UIImage imageWithCGImage:assetRef]];
}
} failureBlock:^(NSError *error) {}];
}
return cell;
}
This works as expected for the first few rows that fit inside of the initial scroll position of the table.
But as I scroll down, cell.nameFirst.text change as expected, while cell.portrait.image gets recycled and starts repeating the images loaded inside of the first scroll position.
Questions
How do I make sure every cell has the appropriate image
Can cell every be nil?
You need to update image whether it is set or not. Your code only sets the image if there isn't one already. Cells get reused as you scroll. So each cell needs to be updated with the image appropriate for the indexPath.
Also note that assetForURL:resultBlock:failureBlock:. It's asynchronous. This means you need to update the cell on the main thread once you get the image in the resultBlock.
cell.nameFirst.text = student.nameFirst;
cell.nameLast.text = student.portrait.assetURL;
// Portrait
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:[NSURL URLWithString:student.portrait.assetURL] resultBlock:^(ALAsset *asset) {
ALAssetRepresentation *representation = [asset defaultRepresentation];
CGImageRef assetRef = [representation fullResolutionImage];
if (assetRef) {
dispatch_async(dispatch_get_main_queue(), ^{
[cell.portrait setImage:[UIImage imageWithCGImage:assetRef]];
});
}
} failureBlock:^(NSError *error) {}];
return cell;
The best way to make sure every cell has the appropriate image is create dictionary and in cellForRowAtIndexPath: check value(image) in the dictionary object at key (I like use indexPath.row as a key). If it is set it up for the cell if it isn't call:
[library assetForURL:[NSURL URLWithString:student.portrait.assetURL] resultBlock:^(ALAsset *asset) {...
and once image is downloaded add it to the dictionary with key (indexPath.row).
You should reload the cell when you download your image, just remember to do it on the main thread.
I would suggest to utilize an image cache. Suppose the image cache has the following API:
typedef void (^completion_t)(id result, NSError* error);
#interface SimpleImageCache : NSObject
/**
Returns the image for the specified URL if it exists, otherwise nil.
*/
- (UIImage*) imageWithURL:(NSURL*)url;
/**
Asychronounsly loads the image from the asset library. The compeltion handler will
be called when the image is available or when an error occured.
The execution context where the compeltion handler will be executed is
implementation defined.
*/
- (void) loadImageWithURL:(NSURL*)url completion:(completion_t)completionHandler;
#end
In your code you would use it as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"studentCell";
StudentTableCell *cell = (StudentTableCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
// Never gets called
}
Student *student = self.studentList[indexPath.row];
cell.nameFirst.text = student.nameFirst;
cell.nameLast.text = student.portrait.assetURL;
// Portrait
NSURL* url = [NSURL URLWithString:student.portrait.assetURL];
UIImage* portrait = [self.imageCache imageWithURL:url];
if (portrait == nil) {
portrait = self.placeholderImage;
[self.imageCache loadImageWithURL:url completion:^(id image, NSError*error){
dispatch_async(dispatch_get_main_queue(), ^{
StudentTableCell* cell = (StudentTableCell *)[tableView cellForRowAtIndexPath:indexPath];
[cell.portrait setImage:image];
});
}];
}
[cell.portrait setImage:portrait];
return cell;
}
Implementation of SimpleImageCache
Warning: It's not tested, but it might give you a jump start, or an idea.
#interface SimpleImageCache ()
#property (nonatomic, strong) NSMutableDictionary* images;
#property (nonatomic, strong) ALAssetsLibrary* assetsLibrary;
#property (nonatomic, strong) UIImage* missingImage;
#end
#implementation SimpleImageCache {
dispatch_queue_t _sync_queue;
}
- (id)init {
self = [super init];
if (self) {
_sync_queue = dispatch_queue_create("sync_queue", NULL);
}
return self;
}
- (NSMutableDictionary*) images {
if (_images == nil) {
_images = [[NSMutableDictionary alloc] init];
}
return _images;
}
- (ALAssetsLibrary*) assetsLibrary {
if (_assetsLibrary == nil) {
_assetsLibrary = [[ALAssetsLibrary alloc] init];
}
return _assetsLibrary;
}
- (UIImage*) imageWithURL:(NSURL*)url {
__block UIImage* image;
dispatch_sync(_sync_queue, ^{
id obj = self.images[url];
if ([obj isKindOfClass:[UIImage class]]) {
image = obj;
}
});
return image;
}
- (void) loadImageWithURL:(NSURL*)url completion:(completion_t)completionHandler {
dispatch_async(_sync_queue, ^{
if (self.images[url] != nil) {
return;
}
self.images[url] = #"pending";
[self.assetsLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
ALAssetRepresentation* representation = [asset defaultRepresentation];
__block UIImage* image = CFBridgingRelease([representation fullResolutionImage]);
dispatch_async(_sync_queue, ^{
if (image == NULL) {
image = self.missingImage;
NSAssert(image, #"image is nil");
}
self.images[url] = image;
if (completionHandler) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
completionHandler(image, nil);
});
}
});
} failureBlock:^(NSError *error) {
if (completionHandler) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
completionHandler(nil, error);
});
}
}];
});
}
#end
I have an app that has a takePhoto UIButton on a UIViewcontroller that enables the user to take a photo by using the imagePickerController. I then want the photo to be placed in a UITableView.
The photo part works and for testing purposes I have the image displayed in a UIImage photoImageView.image
I have added the UITableView delegate and then UITable is called photoTable and the cell is called photoCell. I have tried to figure out the code below for adding the image to the table without success. Any help greatly appreciated.
- (IBAction)takePhoto:(id)sender
{
[self startCameraControllerFromViewController: self usingDelegate: self];
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image;
image = (UIImage *)
[info valueForKey:UIImagePickerControllerOriginalImage];
photoImageView.image=image;
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
[picker dismissViewControllerAnimated:YES completion:nil];
}
-(void) imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissViewControllerAnimated:YES completion:nil];
}
- (BOOL) startCameraControllerFromViewController: (UIViewController*) controller usingDelegate: (id <UIImagePickerControllerDelegate, UINavigationControllerDelegate>) delegate
{
if (([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera] == NO) || (delegate == nil) || (controller == nil)) return NO;
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
cameraUI.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
cameraUI.allowsEditing = NO;
cameraUI.delegate = delegate;
[controller presentViewController:cameraUI animated:YES completion:nil];
return YES;
}
- (UITableViewCell*)tableView:(UITableView*)photoTable cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString* CellIdentifier = #"photoCell";
UITableViewCell* cell = [photoTable dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell.imageView.image = [UIImage imageNamed:#"nameOfImage.jpg"];
return cell;
}
create the image property, and tableview outlet in .h file
#property(nonatomic, strong) UIIImage *photoImage;
#property(nonatomic, strong) IBOutlet UITableView *tableview;
in .m file in didFinishPickingMediaWithInfo: method
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image;
image = (UIImage *)
[info valueForKey:UIImagePickerControllerOriginalImage];
self.photoImage = image;
[self.tableView reloadData]; //call reloadData method to load data with image
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
[picker dismissViewControllerAnimated:YES completion:nil];
}
in cellForRowAtIndexPath: method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.movieTable dequeueReusableCellWithIdentifier:#"cell"];
cell.imageView.image = self.photoImage;
or use array and add image to array in didFinishPickingMediaWithInfo: and use the image
cell.imageView.image = [self.photoArray objectAtIndex:0];
}
In your following method:
imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
Add this line:
[_tableView reloadData];
Return updated number of rows in:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
and in cellForRowAtIndexPath modify your code like this:
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.imageView.image = [UIImage imageNamed:#"nameOfImage.jpg"];
NOTE: if you want to show more than one image, like every image you capture, then save images in an array. and retrieve them in cellForRowAtIndexPath and assign different image to every cell.
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.imageView.image = [UIImage imageNamed:#"nameOfImage.jpg"];
}
Try it, I hope it helps!
I think you have to save images in document directory after capture photo
like:
- (void)saveImage:(UIImage*)imagepk
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:#"savedImage.png"];
UIImage *image = imagepk; // imageView is my image from camera
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:savedImagePath atomically:NO];
// Code for saving image here
}
and then acces from document directory and add in array.
My code below will produce the correct amount of data in array but the display data will only take the last value and display repeated.
For Example:
When i selected the first image then the first image is successfully display in table view.
When i selected the second image then the array will has 2 data but problem is in table view i will get 2 same image (the second selected image). My expected result will be when selected the second image the first image will still be there and the second display at the subsequence row.
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Collector in photoList %#",self.collector);
for (int i = 0; i < collector.count; i++) {
// define the block to call when we get the asset based on the url (below)
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *imageAsset)
{
ALAssetRepresentation *imageRep = [imageAsset defaultRepresentation];
CGImageRef iref = [imageRep fullResolutionImage];
if (iref) {
galleryImage = [UIImage imageWithCGImage:iref];
[self.tableView reloadData];
}
NSLog(#"[imageRep filename] : %#", [imageRep filename]);
};
NSLog(#"Collector %#",self.collector);
// get the asset library and fetch the asset based on the ref url (pass in block above)
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc]init];
[assetslibrary assetForURL:[collector objectAtIndex:i] resultBlock:resultblock failureBlock:nil];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.imageView.image = galleryImage;
NSLog(#"Gallery image is %#",self.galleryImage);
return cell;
}
EDITED!
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Collector in photoList %#",self.collector);
for (int i = 0; i < collector.count; i++) {
// define the block to call when we get the asset based on the url (below)
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *imageAsset)
{
ALAssetRepresentation *imageRep = [imageAsset defaultRepresentation];
CGImageRef iref = [imageRep fullResolutionImage];
if (iref) {
galleryImage = [UIImage imageWithCGImage:iref];
//Added mutable array for galleryImage
[photoCollector addObject:galleryImage];
[self.tableView reloadData];
}
NSLog(#"[imageRep filename] : %#", [imageRep filename]);
};
NSLog(#"Collector %#",self.collector);
// get the asset library and fetch the asset based on the ref url (pass in block above)
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc]init];
[assetslibrary assetForURL:[collector objectAtIndex:i] resultBlock:resultblock failureBlock:nil];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//Display image
if(photoCollector.count != 0)
{
cell.imageView.image = [self.photoCollector objectAtIndex:indexPath.row];
}
NSLog(#"This is in cellForRowAtIndexPath");
NSLog(#"Gallery image is %#",self.galleryImage);
// Configure the cell...
return cell;
}
EDITED code at picker didFinishPickingMediaWithInfo!!
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// Initialize View Controller
PhotosListViewController *photoListViewController = [[PhotosListViewController alloc]initWithNibName:#"PhotosListViewController" bundle:nil];
ImageModel *imgModel = [[ImageModel alloc]init];
// get the ref url
imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
//set the imageUrl to the imageModel url in property ?
imgModel.url = imageURL;
[self.collector addObject:imageURL];
photoListViewController.urlCollector = self.collector;
NSLog(#"Collector in root %#",self.collector);
[picker dismissViewControllerAnimated:YES completion:nil];
[self.navigationController pushViewController:photoListViewController animated:YES];
}
EDITED FULL CODE!!
RootViewController.m
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// Initialize View Controller
PhotosListViewController *photoListViewController = [[PhotosListViewController alloc]initWithNibName:#"PhotosListViewController" bundle:nil];
// get the ref url
imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
[self.collector addObject:imageURL];
photoListViewController.urlCollector = self.collector;
NSLog(#"Collector in root %#",self.collector);
[picker dismissViewControllerAnimated:YES completion:nil];
[self.navigationController pushViewController:photoListViewController animated:YES];
}
ImageModel.h
#import <Foundation/Foundation.h>
typedef void(^handler)(UIImage *image);
#interface ImageModel : NSObject
#property (nonatomic, strong) NSURL *imageUrl;
- (void)getImageWithCompletionHandler:(handler)completionBlock;
#end
ImageModel.m
#import "ImageModel.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import <AssetsLibrary/AssetsLibrary.h>
#implementation ImageModel
#synthesize imageUrl;
- (void)getImageWithCompletionHandler:(handler)completionBlock
{
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *imageAsset)
{
ALAssetRepresentation *imageRep = [imageAsset defaultRepresentation];
CGImageRef iref = [imageRep fullResolutionImage];
if (iref) {
UIImage *image = [UIImage imageWithCGImage:iref];
completionBlock(image);
}
};
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc]init];
[assetslibrary assetForURL:self.imageUrl resultBlock:resultblock failureBlock:nil];
}
#end
PhotoListViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
test1 = [[UIImage alloc]init];
self.imageModelObjects = [NSMutableArray array];
for(NSURL *url in self.urlCollector)
{
ImageModel *imageModel = [[ImageModel alloc] init];
imageModel.imageUrl = url;
[self.imageModelObjects addObject:imageModel];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
ImageModel *model = [self.imageModelObjects objectAtIndex:indexPath.row];
[model getImageWithCompletionHandler:^(UIImage *image) {
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = image;
});
}];
return cell;
}
#interface ViewController () <UITableViewDataSource>
#property (nonatomic, strong) NSMutableArray *images;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.images = [[NSMutableArray alloc] init];
NSLog(#"Collector in photoList %#",self.collector);
for (int i = 0; i < collector.count; i++) {
// define the block to call when we get the asset based on the url (below)
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *imageAsset)
{
ALAssetRepresentation *imageRep = [imageAsset defaultRepresentation];
CGImageRef iref = [imageRep fullResolutionImage];
if (iref) {
[self.images addObject:[UIImage imageWithCGImage:iref]];
[self.tableView reloadData];
}
NSLog(#"[imageRep filename] : %#", [imageRep filename]);
};
NSLog(#"Collector %#",self.collector);
// get the asset library and fetch the asset based on the ref url (pass in block above)
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc]init];
[assetslibrary assetForURL:[collector objectAtIndex:i] resultBlock:resultblock failureBlock:nil];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.images.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.imageView.image = self.images[indexPath.row];
return cell;
}
#end
Edited:
ImageModel.h
#import <Foundation/Foundation.h>
typedef void(^handler)(UIImage *image);
#interface ImageModel : NSObject
#property (nonatomic, strong) NSURL *imageURL;
- (void)getImageWithCompletionHandler:(handler)completionBlock;
#end
ImageModel.m
#import "ImageModel.h"
#implementation ImageModel
- (void)getImageWithCompletionHandler:(handler)completionBlock
{
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *imageAsset)
{
ALAssetRepresentation *imageRep = [imageAsset defaultRepresentation];
CGImageRef iref = [imageRep fullResolutionImage];
if (iref) {
UIImage *image = [UIImage imageWithCGImage:iref];
completionBlock(image);
}
};
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc]init];
[assetslibrary assetForURL:self.imageURL resultBlock:resultblock failureBlock:nil];
}
Controller.m
#import "ViewController.h"
#import "ImageModel.h"
#interface ViewController ()
#property (nonatomic, strong) NSMutableArray *imageModelObjects;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.imageModelObjects = [NSMutableArray array];
for(NSURL *url in self.collector)
{
ImageModel *imageModel = [[ImageModel alloc] init];
imageModel.url = url;
[self.imageModelObjects addObject:imageModel]
}
//You can discard the collecter. IF u want the url, u can get from the self.imageModelObjects.
self.collector = nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
ImageModel *model = [self.imageModelObjects objectAtIndex:indexPath.row];
[model getImageWithCompletionHandler:^(UIImage *image) {
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = image;
});
}];
// Configure the cell...
return cell;
}
if (iref)
{
galleryImage = [UIImage imageWithCGImage:iref];
//Added mutable array for galleryImage
[photoCollector addObject:galleryImage];
[photoCollector retain];
//[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"cell %d",indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.text = #"Hello";
cell.imageView.image = [self.photoCollector objectAtIndex:indexPath.row];
}
// Configure the cell.
return cell;
}
My aim is to have a collection view at the footer of my view. The cells are filled with photos from the photo library. I donĀ“t know why but the cells are overlaping each other. Does anybody know why? Here is the code from the ViewController:
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return [self.fotoArray count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"foto_cell";
FotoCell *cell = [self.collectionView
dequeueReusableCellWithReuseIdentifier:cellIdentifier
forIndexPath:indexPath];
Foto *currFoto = [self.fotoArray objectAtIndex:indexPath.row];
// Set the selectedFotoID
[CoreDataManager sharedInstance].selectedFotoId = ((Foto*)[self.fotoArray objectAtIndex:indexPath.row]).objectID;
NSURL *u = [NSURL URLWithString:currFoto.f_path];
[self findImage:u in: cell];
return cell;
}
// Get Photo from Asset Library
-(void)findImage:(NSURL*)u in: (FotoCell*) cell
{
__block FotoCell *blockCell = cell;
//
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
if (iref) {
UIImage *largeimage = [UIImage imageWithCGImage:iref];
//[largeimage retain];
UIImage *thumbnail = [UIImage imageWithCGImage:iref scale:0.15 orientation:UIImageOrientationUp];
[blockCell.fotoThumb setImage:thumbnail];
}
};
//
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
NSLog(#"cant get image - %#",[myerror localizedDescription]);
};
NSURL *asseturl = u;
ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
[assetslibrary assetForURL:asseturl
resultBlock:resultblock
failureBlock:failureblock];
}
And here the Code from my Cell.m class:
#implementation FotoCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)dealloc {
[_fotoThumb release];
[super dealloc];
}
#end
I'm not clear about your code.But I had met this problem before.
The reason is that you add visible view(like image, UILabel,...) in cellForItemAtIndexPath:
When collectionView sequence, all Cell views are overlap together when you scrolling.
You can try to init and imageView in you Cell, then set image name in cellForItemAtIndexPath
You have to set the itemSize of your UICollectionViewFlowLayout instance.