I am intending to add images (via URL string) into a table view. However, the photo images are not displayed in the table. Below is my code for this.
- (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] autorelease];
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectZero];
imageView.tag = kImageValueTag;
[cell.contentView addSubview:imageView];
[imageView release];
}
// Configure the cell...
NSUInteger row = [indexPath row];
Photo *thisPhoto = [self.thisArray objectAtIndex:row];
UIImageView *thisImageView = (UIImageView *)[cell.contentView viewWithTag:kImageValueTag];
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: thisPhoto.imageURL]];
NSLog(#"URL: %#",thisPhoto.imageURL);
thisImageView.image = [UIImage imageWithData:imageData];
return cell;
}
All my images are of different sizes. How do I make the table show the images based on their sizes?
The below blog posts could guide you for downloading the images in cells from internet.
MHLazyTableImages – Efficiently Load Images for Large Tables
HJCache: iPhone cache library for asynchronous image loading and caching.
As you asked for the cell size based on your images, i would recommend you to show all the images in the predefine rectangle and would be same for all.
Although you could alter the size of each the cell based on the images size but it would decrease the performance of your UITableView.
Related
I have a uitableview with a list of people in it. some records have an image and some records do not. If i scroll down through the list it appears correct but if i scroll back up then an image of another person starts to show on other people's cell row where an image should not be. Here is my code for cellForRowAtIndexPath
// START CELL LABELLING FOR TABLE VIEW LIST //
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
Person *person = [arrayOfPersons objectAtIndex:indexPath.row];
NSString *personPhoto = person.personPhoto;
NSString* imgPath = [docPath stringByAppendingPathComponent:
[NSString stringWithFormat:#"%#", personPhoto] ];
if ([[NSFileManager defaultManager] fileExistsAtPath:imgPath]){
NSLog(#"FILE EXISTS");
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(240, 0, 67, 67)];
imageView.image = [UIImage imageWithContentsOfFile:imgPath];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[cell.contentView addSubview:imageView];
}else{
NSLog(#"Does Not Exist");
}
cell.textLabel.text = person.personName;
return cell;
imageView = nil;
personPhoto = #"";
imgPath = #"";
}
// END CELL LABELLING FOR TABLE VIEW LIST //
The reason this is happening is because table cells get re-used.
When you use [tableView dequeueReusableCellWithIdentifier:CellIdentifier], you get back a cell that has already been shown in your table view (for a different index path). You may have already added an image view to this cell for the Person at this previous index path, and nowhere do you remove this image.
Therefore, when the current Person doesn't have a photo, the previous image will remain visible in the cell.
I would recommend creating your own UITableViewCell subclass and adding a UIImageView to it, so that you can easily get a reference back to the image view (or you could use a view tag, if you prefer).
Either way, you need to remove the image view/set the image to nil when the person does not have a photo.
Hello I am trying to use EGOImageView inside a CustomTableViewCell who i made to customize the cell. This is the code where I used the EGOImageView.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString* simpleTableIdentifier = #"Albums";
CustomTableCell* cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (!cell)
{
cell = [[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
NSLog(#"Show once or more times");
}
NSDictionary* dictionary = (NSDictionary*)[self.albumCollection objectAtIndex:indexPath.row];
cell.label.text = [dictionary valueForKey:#"name"];
EGOImageView* imageView = [[EGOImageView alloc] initWithPlaceholderImage:[UIImage imageWithContentsOfFile:#""]];
[imageView setImageURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=small&access_token=%#", (NSString*)[dictionary valueForKey:#"id"], [[FBSession activeSession] accessToken]]]];
[imageView setFrame:CGRectMake(0.0f,0.0f,78.0f,78.0f )];
[cell.iView addSubview:imageView];
[imageView release];
The image on each cell loading the same image. Would it be because it reused the cell while loading the image.
I found a problem I can't think of why the problem happened. I used the graph api to grab the image https://graph.facebook.com/%#/picture?type=small&access_token=%# where the first parameter was the album id.
To make myself easy to see the problem I only used one album on the cell, no matter what album i used the same photo turned up. But when I copy the link to the browser, the actual photo url shown on the address bar with the image shown and it shown the correct photos.
Does anyone know what was wrong.
Here is example. It loads user pics from some server in background and updates cell image. Note that imageView.image is set to nil at the beginning. This is dome for the case of cell reuse so that you will have no image rather than wrong image for the time while its downloading.
One more thing to add is that, would be also good to have a cache so that it does not download images all the time. Another nice thing is to not download images in edge networks.
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TransactionCell";
NSMutableArray *data = searching ? searchResult : dataSource;
NSDictionary *object = [data objectAtIndex:[indexPath row]];
UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithIdentifier:CellIdentifier] autorelease];
}
cell.imageView.image = nil;
cell.textLabel.text = #"Your cell text";
NSString *contact = #"foo#gmail.com";
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *imgData = [appDelegate addUserPic:contact];
if (imgData == nil && netStatus == ReachableViaWiFi) {
NSString *url = [NSString stringWithFormat:#"http://somehost.com/userpic/%#", contact];
imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
}
dispatch_async(dispatch_get_main_queue(), ^{
UITableViewCell *updateCell = [self.tableView cellForRowAtIndexPath:indexPath];
if (updateCell) {
if (imgData) {
[appDelegate setUserPic:contact imgData:imgData];
updateCell.imageView.image = [UIImage imageWithData:imgData];
} else {
updateCell.imageView.image = nil;
}
/* This forces the cell to show image as now
it has normal bounds */
[updateCell setNeedsLayout];
}
});
});
return cell;
}
I am loading a tableView with 500 rows. The problem is that in each row there is a different picture. Or when I use dequeueReusableCellWithIdentifier, those picture are just loaded again and the real pictures I am looking for are not shown (I just have about 8 different pictures : the first 8 loaded on my screen). If I don't use the dequeureReusableCellIdentifier, all the picture are loaded. But will it slow the displaying ?
Here is the code (I am currently working on getting the picture cached) :
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CustomCellIdentifier = #"CustomCellIdentifier";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier: CustomCellIdentifier];
NSLog(#"Launching CellForRowAtIndexPath");
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell"
owner:self options:nil];
if ([nib count] > 0) {
cell = self.profilCell;
} else {
NSLog(#"failed to load CustomCell nib file!");
}
}
NSUInteger row = [indexPath row];
NSDictionary *rowData = [listProfils objectAtIndex:row];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:nameValueTag];
nameLabel.text = [rowData objectForKey:#"name"];
NSString *finalId = [NSString stringWithFormat:#"http://graph.facebook.com/%#/picture", [rowData objectForKey:#"id"]];
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:finalId]]];
[profilPic setImage:image];
return cell;
}
THank you ! :)
It looks like you have an ivar profilPic that is probably an outlet that gets linked when you load a new cell nib. If that's the case, it's always going to point to the last cell that you loaded and won't change the image in the cell you've just dequeued. Instead of using an outlet, you might want to identify that custom view some other way, like a tag. So, if you set the profile pic UIImageView's tag to 100, for example, in Interface Builder, you could do something like this:
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:finalId]]];
UIImageView* cellImageView = (UIImageView*)[cell viewWithTag:100];
[cellImageView setImage:image];
Also, I just want to point out that -dataWithContentsOfURL: will load the URL synchronously on the main thread. If you're testing in the simulator on a fast connection, this will work pretty well. If, however, you are on 3G in SoHo on Friday afternoon... your app will probably start being killed by the watchdog.
I just met this problem, my solution is hold a private NSMutableDictionary to store the new images which asynchronously loaded from web before, use my identifier as key, UIImageView as Object (because I need to load the icon image first), when web image is ready, change it, When tableView dequeue return's null, I can read the original UIImage from my own cache.
Something like this.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
UIImageView *imageView = [thumbnailCache objectForKey:identifier];
if (!imageView) {
cell.imageView.image = [UIImage imageNamed:#"icon.png"];
[thumbnailCache setObject:cell.imageView forKey:identifier];
} else {
cell.imageView.image = imageView.image;
}
}
When I load the actual image from web, refresh the thumbnail cache.
asynchronously_load_image_from_web(^(UIImage *image) {
cell.imageView.image = image;
[thumbnailCache setObject:cell.imageView forKey:identifier];
});
I am using an image to display the whole content of a UITableViewCell and it's set using the backgroundView property.
My problem is that it is always scaled to fit the cell. Is there a way to disable scaling in this case, so I can provide the 480 pixel version only and it just gets cropped when orientation is portrait?
I'm doing it like this:
- (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] autorelease];
}
UIImageView *bgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"menu.0%d.large.png", indexPath.row+1]]];
UIImageView *selectedBgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"menu.0%d.large.selected.png", indexPath.row+1]]];
cell.backgroundView = bgView;
cell.selectedBackgroundView = selectedBgView;
[bgView release];
[selectedBgView release];
return cell;
}
I tried using two versions of the images to switch between them when orientation is changed. This works so far, too, but it's got the drawback that you always see the scaling while the animation is processed.
Thanks for your help
Arne
Set the content mode of your background image views.
bgView.contentMode = UIViewContentModeTopLeft;
selectedBgView.contentMode = UIViewContentModeTopLeft;
This tells the UIImageView to put its image in the top left corner rather than scale it to fit.
I did not try this on the simulator or device, but the following might work:
- (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] autorelease];
}
// New!
cell.backgroundView.clipsToBounds = YES;
UIImageView *bgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"menu.0%d.large.png", indexPath.row+1]]];
UIImageView *selectedBgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"menu.0%d.large.selected.png", indexPath.row+1]]];
// New!
bgView.center = CGPointMake(160, 25); // Adjust the y-Value to be exactly half of the height of your cell
bgView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin; // Not quite sure whether these two will work, maybe you have to play a little with the Masks
cell.backgroundView = bgView;
cell.selectedBackgroundView = selectedBgView;
[bgView release];
[selectedBgView release];
return cell;
}
Let me know whether you managed to get it running.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
is was you looking for, I think.
more information :
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html
I have stored the videos and the thumbnail images of the videos in Documents folder. And I have given the path in plist. In plist I took an array and I added directories to the array.
And in the dictionary I stored the image path
/Users/srikanth/Library/Application Support/iPhone Simulator/User/Applications/9E6E8B22-C946-4442-9209-75BB0E924434/Documents/image1
for key imagePath.
for video
/Users/srikanth/Library/Application Support/iPhone Simulator/User/Applications/9E6E8B22-C946-4442-9209-75BB0E924434/Documents/video1.mp4
for key filePath.
I used following code but it is not working. I am trying only for images. I need the images to be loaded in the table in each cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
UIImageView *image2;
image2.frame = CGRectMake(0.0f, 0.0f, 80.0f, 80.0f);
image2.backgroundColor = [UIColor clearColor];
}
NSDictionary *dictOfplist = [cells objectAtIndex:indexPath.row];
NSString *path = [dictOfplist objectForKey:#"imagePath"];
NSLog("path: %#", path);
return cell;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Library";
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Close" style:UIBarButtonItemStyleBordered target:self action:#selector(close:)];
NSString* plistPath = [[NSBundle mainBundle] pathForResource:#"details" ofType:#"plist"];
contentArray = [NSArray arrayWithContentsOfFile:plistPath];
cells = [[NSMutableArray alloc]initWithCapacity:[contentArray count]];
for(dCount = 0; dCount < [contentArray count]; dCount++)
[cells addObject:[contentArray objectAtIndex:dCount]];
}
I got the path of the images are from the plist.
But, how can I extract the image from the path.
The output od NSLog: is
path: /Users/srikanth/Library/Application Support/iPhone Simulator/User/Applications/9E6E8B22-C946-4442-9209-75BB0E924434/Documents/snook.jpg
How can I get the image from it and store in cell.imageView.image ?
How can I make this work.
Thank you.
I see some problems in your code:
When you are creating the UITableViewCell instance, you create an UIImageView image2 that is not assigned and therefore leaks memory. Is not normal ?
You do not need to get a reference to the UIImageView of the cell by tag. An UITableViewCell already has an UIImageView and its image can be set with the cell.imageView.image property.
Where are you loading the UIImage ? You say you are storing the image path, but there is no code for loading image from this path.