I have a table view loading in the below manner. If a condition is met I need to add a particular image above the cell.imageview. Also the images are coming in different dimensions. Below is my code can anybody point me in where i am going wrong.
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
if(array==nil||[array count]==0)
{
}
else
{
NSMutableDictionary *dicttable=[array objectAtIndex:indexPath.row];
NSString *head=[dicttable objectForKey:#"name"];
NSString *type=[dicttable objectForKey:#"type"];
NSString *imgUrl = [dicttable objectForKey:#"image"];;
if(imgUrl!=nil)
{
if(![[ImageCache sharedImageCache] hasImageWithKey:imgUrl])
{
cell.imageView.image = [UIImage imageNamed:#"noimage_icon.png"];
NSArray *myArray = [NSArray arrayWithObjects:cell.imageView,imgUrl,#"noimage_icon.png",[NSNumber numberWithBool:NO],nil];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate performSelectorInBackground:#selector(updateImageViewInBackground:) withObject:myArray];
cell.imageView.frame=CGRectMake(0,0,48,48);
cell.imageView.bounds=CGRectMake(0,0,48,48);
[cell.imageView setClipsToBounds:NO];
}
else
{
cell.imageView.image = [[ImageCache sharedImageCache] getImagefromCacheOrUrl:imgUrl];
cell.imageView.frame=CGRectMake(0,0,48,48);
cell.imageView.bounds=CGRectMake(0,0,48,48);
[cell.imageView setClipsToBounds:NO];
}
}
else
{
cell.imageView.image = [UIImage imageNamed:#"noimage_icon.png"];
}
if([type isEqualToString:#"YES"])
{
UIImageView* img = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"bluel.png"]];
[cell setBackgroundView:img];
[img release];
cell.textLabel.text = head;
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.detailTextLabel.textColor=[UIColor grayColor];
cell.detailTextLabel.text = subtitle1;
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
}
else
{
UIImageView* img = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"wnew1.png"]];
[cell setBackgroundView:img];
[img release];
cell.textLabel.text = head;
cell.textLabel.backgroundColor = [UIColor clearColor];
[cell.imageView addsubview:spclimage]
cell.textLabel.text = head;
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.detailTextLabel.textColor=[UIColor grayColor];
cell.detailTextLabel.text = subtitle1;
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
}
}
return cell;
Here the problem is only in the last row the special image is adding. Not in all rows. Also the image view size is different in all the time the tableview is reloading?
A couple of thoughts:
The updateImageViewInBackground seems suspect, as the name suggests that you're updating an image view, but you don't specify which cell you're updating.
I also see you doing a addSubview:spclimage. Obviously, if that spclimage was on another cell, as soon as you do addSubview, it will be removed from the previous location before being added to current cell. In fact, just the notion of adding an image as a subview of an existing imageview is curious.
If your cache doesn't have the image yet, I see where you're initializing the image with noimage_icon.png, but I don't see where you're actually updating the image view. You say updateImageViewInBackground is "then updating the image". Do you mean setting the image property for the imageView for this cell for this indexPath? Or maybe updating spclimage? If so, that's problematic.
The typical pattern (using GCD) for this would be:
cell.imageView.image = [UIImage imageNamed:#"noimage_icon.png"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *image = ... // do whatever you need to do to get the image, load cache, etc.
// ok, now that you have the image, dispatch the update of the UI back to the main queue
dispatch_async(dispatch_get_main_queue(), ^{
// because we're doing this asynchronously, make sure the cell is still
// visible (it could have scrolled off and the cell was dequeued and
// reused), so we're going to ask the tableview for the cell for that
// indexPath, and it returns `nil` if it's not visible. This method is
// not to be confused with the similarly named `UITableViewControllerDelegate`
// method.
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
// if the image view is still visible, update it
if (cell)
{
cell.imageView.image = image;
}
});
});
Related
I am using NSOperationQueue for caching images in background.
Here is the code below:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"CellIdentifier";
UITableViewCell *cell;
cell = [self.mUpcomEventsTable dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
UIImageView *imgView;
UILabel *lblEventName;
UILabel *lblDate;
UILabel *lblTime;
if(self.mEventNameArr != NULL)
{
NSString *imageUrlString = [NSString stringWithFormat:#"%#", [self.mEventImageArr objectAtIndex:indexPath.row]];
UIImage *cachedImage = [self.imageCache objectForKey:imageUrlString];
NSLog(#"cache:%#", self.imageCache);
imgView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 80, 90)];
lblEventName = [[UILabel alloc]initWithFrame:CGRectMake(90, 10, 200, 30)];
lblEventName.text = [self.mEventNameArr objectAtIndex: indexPath.row];
lblEventName.font = [UIFont fontWithName:#"Helvetica-Bold" size:18];
lblDate = [[UILabel alloc]initWithFrame:CGRectMake(90, 50, 100, 30)];
lblDate.text = [self.mEventDateArr objectAtIndex:indexPath.row];
lblTime = [[UILabel alloc]initWithFrame:CGRectMake(190, 50, 100, 30)];
lblTime.text = [self.mEventTimeArr objectAtIndex:indexPath.row];
strEventName = lblEventName.text;
strEventDate = lblDate.text;
strEventTime = lblTime.text;
if (cachedImage)
{
imgView.image = cachedImage;
}
else
{
// you'll want to initialize the image with some blank image as a placeholder
imgView.image = [UIImage imageNamed:#"Placeholder.png"];
// now download in the image in the background
NSLog(#"queue:%#",self.imageDownloadingQueue);
[self.imageDownloadingQueue addOperationWithBlock:^{
NSURL *imageUrl = [NSURL URLWithString:imageUrlString];
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
UIImage *image = nil;
if (imageData)
image = [UIImage imageWithData:imageData];
if (image)
{
[self.imageCache setObject:image forKey:imageUrlString];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
UITableViewCell *updateCell = [tableView cellForRowAtIndexPath:indexPath];
if (updateCell)
imgView.image = cachedImage;
}];
}
}];
}
}
else cell.textLabel.text = #"No event";
[cell addSubview:imgView];
[cell addSubview:lblEventName];
[cell addSubview:lblDate];
[cell addSubview:lblTime];
return cell;
}
It is not going in this line
[self.imageDownloadingQueue addOperationWithBlock:^{
it go outside from this. Why so, please help for above.
Took idea from here link.
There are a lot of disadvantage of using NSOperationQueue. One of them is your image will flick when every time you scroll the UITableView.
I'd suggest you to use this AsyncImageView. I've used it and it work wonders. To call this API:
ASyncImage *img_EventImag = alloc with frame;
NSURL *url = yourPhotoPath;
[img_EventImage loadImageFromURL:photoPath];
[self.view addSubView:img_EventImage]; // In your case you'll add in your TableViewCell.
It's same as using UIImageView. Easy and it does most of the things for you. AsyncImageView includes both a simple category on UIImageView for loading and displaying images asynchronously on iOS so that they do not lock up the UI, and a UIImageView subclass for more advanced features. AsyncImageView works with URLs so it can be used with either local or remote files.
Loaded/downloaded images are cached in memory and are automatically cleaned up in the event of a memory warning. The AsyncImageView operates independently of the UIImage cache, but by default any images located in the root of the application bundle will be stored in the UIImage cache instead, avoiding any duplication of cached images.
The library can also be used to load and cache images independently of a UIImageView as it provides direct access to the underlying loading and caching classes.
This has been driving me crazy for the better part of the day.
I've got a UITableView with UIImageViews. These imageviews load a locally saved PNG-file in the cellForRow-function of the tableview, and this works fine except the tableview will stop scrolling for a fraction of a second when a cell with an image in it scrolls into sight so to speak. I've trawled StackOverflow and google for an answer but I've come up short - so any help will be greatly appreciated.
Here is my code for the CellForRow-function:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MyIdentifier"] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if([currSection isEqualToString:#"composer"]){
MySlide *s = [slidesArray objectAtIndex:indexPath.row];
cell.textLabel.hidden = YES;
UIImageView *whiteView = [[UIImageView alloc] initWithFrame:CGRectMake((projectsTable.frame.size.width/2)-150, 4, 204.8, 153.6)];
if([s.slideImage isEqualToString:#""] || s.slideImage == nil){
//no custom image in this cell - go with default background image
whiteView.image = [UIImage imageNamed:#"cellback2.png"];
whiteView.backgroundColor = [UIColor whiteColor];
}else{
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
NSData *data = [[NSData alloc] initWithContentsOfFile:s.slideImage];
UIImage *im = [[UIImage alloc] initWithData:data];
whiteView.image = im;
whiteView.image = [self imageWithImage:whiteView.image CovertToSize:CGSizeMake(204.8,153.6)];
whiteView.backgroundColor = [UIColor whiteColor];
}
[cell.contentView addSubview:whiteView];
[whiteView release];
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
There are a couple of changes to be made, first off the UIImageViews should be added when the cell is generated, rather than every time tableView:cellForRowAtIndexPath: is hit (as #Vishy suggests). Secondly you should cache the images you are loading from the documents directory ([UIImage imageNamed:] does this automatically for bundle resources).
#interface MyViewController () {
NSMutableDictionary *_imageCache;
}
#end
#implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
// other viewDidLoad stuff...
_imageCache = [[NSMutableDictionary alloc] init];
}
- (void)viewDidUnload {
[super viewDidUnload];
// other viewDidUnload stuff...
[_imageCache release];
_imageCache = nil;
}
- (void)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MyIdentifier"] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
UIImageView *whiteView = [[UIImageView alloc] initWithFrame:CGRectMake((projectsTable.frame.size.width/2)-150, 4, 204.8, 153.6)];
whiteView.tag = 111;
whiteView.backgroundColor = [UIColor whiteColor];
[cell.contentView addSubview:whiteView];
[whiteView release];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.hidden = YES;
}
UIImageView* iView = (UIImageView*) [cell.contentView viewWithTag:111];
if([currSection isEqualToString:#"composer"]) {
MySlide *s = [slidesArray objectAtIndex:indexPath.row];
if([s.slideImage isEqualToString:#""] || s.slideImage == nil) {
//no custom image in this cell - go with default background image
iView.image = [UIImage imageNamed:#"cellback2.png"];
}
else {
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
// use the image path as the cache key
UIImage *theImage = [_imageCache objectForKey:s.slideImage];
if (theImage == nil) {
// load the image and save into the cache
theImage = [UIImage imageWithContentsOfFile:s.slideImage];
theImage = [self imageWithImage:theImage CovertToSize:CGSizeMake(204.8, 153.6)];
[_imageCache setObject:theImage forKey:s.slideImage];
}
iView.image = theImage;
}
}
}
#end
As a general rule, tableView:cellForRowAtIndexPath: is a method you need to get out of fast, so loading images from disk should be avoided wherever possible.
Change the code as per below...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MyIdentifier"] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
UIImageView *whiteView = [[UIImageView alloc] initWithFrame:CGRectMake((projectsTable.frame.size.width/2)-150, 4, 204.8, 153.6)];
whiteView.tag = 111;
whiteView.backgroundColor = [UIColor whiteColor];
[cell.contentView addSubview:whiteView];
[whiteView release];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.hidden = YES;
}
UIImageView* iView = (UIImageView*) [cell.contentView viewWithTag:111];
if([currSection isEqualToString:#"composer"])
{
MySlide *s = [slidesArray objectAtIndex:indexPath.row];
if([s.slideImage isEqualToString:#""] || s.slideImage == nil)
{
//no custom image in this cell - go with default background image
iView.image = [UIImage imageNamed:#"cellback2.png"];
}
else
{
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
iView.image = [UIImage imageWithContentsOfFile:s.slideImage];
iView.image = [self imageWithImage:iView.image CovertToSize:CGSizeMake(204.8,153.6)];
}
}
}
There is also a delay the first time each UIImage is displayed. See this post for details on prompting the work at cache time rather than display time:
Setting image property of UIImageView causes major lag
So I have some issues with my tableview. I have a custom label that I put into a tableview cell to add a little better graphics than the standard UItableviewcell. However, I was running into my first problem,
the text labels that I had on the cells were changing with and over writing each other upon scrolling, only when the cells had moved off screen and then came back. Upon some research I found that maybe it had something to do with dequeueReusableCellWithIdentifier: so I adjusted my code. this is where problem two comes in.
When I load the table everything is in its right place, correct looking and all. However when I start to scroll down I can get to all of my cells except the last one, it will go to the very bottom of the 8th cell and freeze, but I should have 9 cells loaded.
I am quite confused by some of this, could anyone provide some code or guidance to help me along?
Thanks.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Run");
CoCoachAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
static NSString *CellIdentifier = #"Cell";
UILabel *label;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSArray *keys = [[appDelegate rowersDataStore] allKeys];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// Configure the cell...
label = [[[UILabel alloc] initWithFrame:CGRectMake(20, 15, cell.bounds.size.width - 10, 30)] autorelease];
label.font = [UIFont boldSystemFontOfSize:16];
label.backgroundColor = [UIColor clearColor];
label.shadowColor = [UIColor colorWithWhite:1.0 alpha:0.5];
label.shadowOffset = CGSizeMake(0,1);
label.textColor = [UIColor colorWithRed:0x4c/255.0 green:0x4e/255.0 blue:0x48/255.0 alpha:1.0];
switch (indexPath.section) {
case 0:
label.frame = CGRectMake(0, 15, cell.bounds.size.width - 10, 30);
label.textAlignment = UITextAlignmentCenter;
break;
case 1:
label.textAlignment = UITextAlignmentLeft;
UIImage *accessoryImage = [UIImage imageNamed:#"content_arrow.png"];
UIImageView *accessoryView = [[UIImageView alloc] initWithImage:accessoryImage];
cell.accessoryView = accessoryView;
[accessoryView release];
break;
}
UIImageView *imgView = [[UIImageView alloc] initWithFrame:cell.frame];
UIImage* img = [UIImage imageNamed:#"odd_slice.png"];
imgView.image = img;
cell.backgroundView = imgView;
[imgView release];
//Selected State
UIImage *selectionBackground = [UIImage imageNamed:#"row_selected.png"];
UIImageView *selectionView = [[UIImageView alloc] initWithFrame:cell.frame];
selectionView.image = selectionBackground;
cell.selectedBackgroundView = selectionView;
[selectionView release];
}
switch (indexPath.section) {
case 0:
[label setText:#"Click to add new rower"];
break;
case 1:
[label setText:[[[appDelegate rowersDataStore] objectForKey:[keys objectAtIndex:indexPath.row]] objectForKey:#"Name"]];
break;
}
//Adds Text
[cell addSubview:label];
return cell;
}
I see several issues here. First, the general structure of this method should be...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
// Attempt to dequeue the cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// If cell does not exist, create it, otherwise customize existing cell for this row
if (cell == nil) {
// Create cell
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// Configure cell:
// *** This section should configure the cell to a state independent of
// whatever row or section the cell is in, since it is only executed
// once when the cell is first created.
}
// Customize cell:
// *** This section should customize the cell depending on what row or section
// is passed in indexPath, since this is executed every time this delegate method
// is called.
return cell;
}
Basically, UITableView uses a single UITableViewCell instance to draw every cell in the table view. So, when you first create this cell, you should configure it to a state that is common to all cells that will use this instance, independent of whatever row or section is passed in indexPath. In your example, this involves creating the label, image, and background image instances and adding them as subviews to the cell.
Once the cell is created (aka outside the if (cell == nil) statement), you should customize its properties according to how the cell should look for the specific row and section contained in indexPath. Since you want to access your custom label in this part of the code, I assigned a tag value to it so that we can access it beyond the code segment where it was created using viewWithTag:. Once we have the label, we can customize it according to the section as well as do anything else we want, such as customize the accessory view.
I slightly modified/cleaned up your code below. This is by far not the most efficient or elegant way to do what you want to do, but I was trying to keep as much of your code as possible. I haven't tested this, but if you try it it should work:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Run");
CoCoachAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSArray *keys = [[appDelegate rowersDataStore] allKeys];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// Configure the cell...
UILabel *label;
label = [[[UILabel alloc] initWithFrame:CGRectMake(20, 15, cell.bounds.size.width - 10, 30)] autorelease];
label.font = [UIFont boldSystemFontOfSize:16];
label.opaque = NO;
label.backgroundColor = [UIColor clearColor];
label.shadowColor = [UIColor colorWithWhite:1.0 alpha:0.5];
label.shadowOffset = CGSizeMake(0,1);
label.textColor = [UIColor colorWithRed:0x4c/255.0 green:0x4e/255.0 blue:0x48/255.0 alpha:1.0];
label.tag = 100;
[cell addSubview:label];
[label release];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:cell.frame];
UIImage* img = [UIImage imageNamed:#"odd_slice.png"];
imgView.image = img;
cell.backgroundView = imgView;
[imgView release];
//Selected State
UIImage *selectionBackground = [UIImage imageNamed:#"row_selected.png"];
UIImageView *selectionView = [[UIImageView alloc] initWithFrame:cell.frame];
selectionView.image = selectionBackground;
cell.selectedBackgroundView = selectionView;
[selectionView release];
}
UILabel *lbl = (UILabel *)[cell viewWithTag:100];
switch (indexPath.section) {
case 0:
cell.accessoryView = nil;
lbl.frame = CGRectMake(0, 15, cell.bounds.size.width - 10, 30);
lbl.textAlignment = UITextAlignmentCenter;
[label setText:#"Click to add new rower"];
break;
case 1:
UIImage *accessoryImage = [UIImage imageNamed:#"content_arrow.png"];
UIImageView *accessoryView = [[UIImageView alloc] initWithImage:accessoryImage];
cell.accessoryView = accessoryView;
[accessoryView release];
lbl.frame = CGRectMake(20, 15, cell.bounds.size.width - 10, 30);
lbl.textAlignment = UITextAlignmentLeft;
[lbl setText:[[[appDelegate rowersDataStore] objectForKey:[keys objectAtIndex:indexPath.row]] objectForKey:#"Name"]];
break;
}
return cell;
}
Table view cell management has driving me crazy from past two days. Please check the code below and I will explain you the problem in detail..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UILabel *nameLabel,*sugarLabel,*searchNameLabel,*searchSugarLabel;
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
CGFloat width = [UIScreen mainScreen].bounds.size.width - 50;
CGFloat height = 20;
CGRect frame = CGRectMake(10.0f, 10.0f, width, height);
if(isSearchOn)
{
searchNameLabel = [[UILabel alloc] initWithFrame:frame];
searchNameLabel.textColor = [UIColor blackColor];
searchNameLabel.backgroundColor = [UIColor clearColor];
searchNameLabel.textAlignment = UITextAlignmentLeft;
searchNameLabel.font = [UIFont systemFontOfSize:14.0f];
searchNameLabel.tag=260;
[cell.contentView addSubview:searchNameLabel];
[searchNameLabel release];
searchSugarLabel= [[UILabel alloc] initWithFrame:frame];
searchSugarLabel.textColor = [UIColor blackColor];
searchSugarLabel.backgroundColor = [UIColor clearColor];
searchSugarLabel.textAlignment = UITextAlignmentLeft;
searchSugarLabel.font = [UIFont systemFontOfSize:14.0f];
searchSugarLabel.tag=160;
[searchSugarLabel setHidden:YES];
[cell.contentView addSubview:searchSugarLabel];
[searchSugarLabel release];
}
else{
nameLabel = [[UILabel alloc] initWithFrame:frame];
nameLabel.textColor = [UIColor blackColor];
nameLabel.backgroundColor = [UIColor clearColor];
nameLabel.textAlignment = UITextAlignmentLeft;
nameLabel.font = [UIFont systemFontOfSize:14.0f];
nameLabel.tag=60;
[cell.contentView addSubview:nameLabel];
[nameLabel release];
sugarLabel= [[UILabel alloc] initWithFrame:frame];
sugarLabel.textColor = [UIColor blackColor];
sugarLabel.backgroundColor = [UIColor clearColor];
sugarLabel.textAlignment = UITextAlignmentLeft;
sugarLabel.font = [UIFont systemFontOfSize:14.0f];
sugarLabel.tag=160;
[sugarLabel setHidden:YES];
[cell.contentView addSubview:sugarLabel];
[sugarLabel release];
}
}
else {
if(isSearchOn)
{
searchNameLabel=(UILabel *)[cell.contentView viewWithTag:260];
searchSugarLabel=(UILabel *)[cell.contentView viewWithTag:160];
}
else{
nameLabel=(UILabel *)[cell.contentView viewWithTag:60];
sugarLabel=(UILabel *)[cell.contentView viewWithTag:160];
}
}
if (isSearchOn) {
cellValue = [searchResult objectAtIndex:indexPath.row];
searchSugarLabel.text=cellValue.sugarId;
NSString *searchText = [NSString stringWithFormat:#"%# %#", cellValue.firstName, cellValue.lastName];
searchNameLabel.text=searchText;
NSLog(#"%#",searchNameLabel.text);
NSLog(#"%#",searchSugarLabel.text);
}
else {
NSString *contact=[contactKeys objectAtIndex:[indexPath section]];
NSArray *contactSection=[contactNames objectForKey:contact];
sugar=[db getSugarId:#"Contacts" bySection:contact andIndex:indexPath.row];
NSString *cellText = [contactSection objectAtIndex:[indexPath row]];
// split the text by the : to get an array containing { "AAA", "BBB" }
NSArray *splitText = [cellText componentsSeparatedByString:#":"];
// form a new string of the form "BBB AAA" by using the individual entries in the array
NSString *contactText = [NSString stringWithFormat:#"%# %#", [splitText objectAtIndex:1], [splitText objectAtIndex:0]];
nameLabel.text = contactText;
sugarLabel.text = sugar;
}
return cell;
}
Contacts is a class which has the properties firstName,lastName and sugar id in it..I am assigning the properties of a contacts class to the variables in the database method and returning an array of contact objects. searchResult is now an array of contact objects.The problem is when I logged the contents on the console the database gets everything in it and returns an array of contacts.The contacts in the searchResult points to different memory locations but when I try to debug the cellForRowAtIndexPath method after it gets 6 contacts..the 7th contact points to the same memory location as the 1st and it repeats thus in the searchNameLabel.text it returns a null and indexPath points to nil...I think it is cell re use issue and I accept that I am very bad in that..I need to figure this out as I am going to finish off my project with this...please guys help me...
This happens only when I try to search for the contacts. It works fine when I try to load all the contacts onto the table..
You are initializing your subviews in the if(cell== nil) block, but in the corresponding else-block, you overwrite them again.
You should rethink your design: Do not load different views by searchon, but set their properties depending on searchon
if(cell == nil){
//do all initializing
}
if(searchon){
//set view/label properties for searching style
} else {
//set view/label properties for not-searching style
}
another approach could be to have totally separated NIB files for the searchon/!searchon
if(searchon){
static NSString *SearchOnCellIdentifier = #"SearchOnCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: SearchOnCellIdentifier];
if (cell == nil){
//load cell from extra nib
}
} else {
static NSString *SearchOFFCellIdentifier = #"SearchOFFCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: SearchOFFCellIdentifier];
if (cell == nil){
//load cell from extra nib
}
}
NOTE: I never did that and it is not tested.
Here's what I need to do:
Load 66px x 66px images into the table cells in the MainViewController table.
each TableCell has a unique image.
But how? Would we use cell.image?
cell.image = [UIImage imageNamed:#"image.png"];
If so, where? Is an if/else statement required?
To load each cell's labels, MainViewController uses an NSDictionary and NSLocalizedString like so:
//cell one
menuList addObject:[NSDictionary dictionaryWithObjectsAndKeys:
NSLocalizedString(#"PageOneTitle", #""), kTitleKey,
NSLocalizedString(#"PageOneExplain", #""), kExplainKey, nil]];
//cell two
menuList addObject:[NSDictionary dictionaryWithObjectsAndKeys:
NSLocalizedString(#"PageOneTitle", #""), kTitleKey,
NSLocalizedString(#"PageOneExplain", #""), kExplainKey, nil]];
...
// this is where MainViewController loads the cell content
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell = (MyCustomCell*)[tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
if (cell == nil)
{
cell = [[[MyCustomCell alloc] initWithFrame:CGRectZero reuseIdentifier:kCellIdentifier] autorelease];
}
...
// MyCustomCell.m adds the subviews
- (id)initWithFrame:(CGRect)aRect reuseIdentifier:(NSString *)identifier
{
self = [super initWithFrame:aRect reuseIdentifier:identifier];
if (self)
{
// you can do this here specifically or at the table level for all cells
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// Create label views to contain the various pieces of text that make up the cell.
// Add these as subviews.
nameLabel = [[UILabel alloc] initWithFrame:CGRectZero]; // layoutSubViews will decide the final frame
nameLabel.backgroundColor = [UIColor clearColor];
nameLabel.opaque = NO;
nameLabel.textColor = [UIColor blackColor];
nameLabel.highlightedTextColor = [UIColor whiteColor];
nameLabel.font = [UIFont boldSystemFontOfSize:18];
[self.contentView addSubview:nameLabel];
explainLabel = [[UILabel alloc] initWithFrame:CGRectZero]; // layoutSubViews will decide the final frame
explainLabel.backgroundColor = [UIColor clearColor];
explainLabel.opaque = NO;
explainLabel.textColor = [UIColor grayColor];
explainLabel.highlightedTextColor = [UIColor whiteColor];
explainLabel.font = [UIFont systemFontOfSize:14];
[self.contentView addSubview:explainLabel];
//added to mark where the thumbnail image should go
imageView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 66, 66)];
[self.contentView addSubview:imageView];
}
return self;
}
If the image is going to be the same for every cell, i.e., it's part of that type of cell, you could load it in MyCustomCell's init, using self.image = [UIImage imageNamed:"blabla"];
Otherwise, if the image will be different for different cells, it would be more logical to put it in tableView:cellForRowAtIndexPath:
Yes, cell.image is deprecated. use imageview.image instead in the default TableViewCell. I am not sure why custom cell was required to do what the standard tableviewcell already does (title, subtitle, and an image using UITableViewStyleSubtitle)
It works now. You were right, Seventoes, about putting it in tableView:cellForRowAtIndexPath:
indexPath.row was what I was I missing. The working result goes like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell = (MyCustomCell*)[tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
if (cell == nil)
{
cell = [[[MyCustomCell alloc] initWithFrame:CGRectZero reuseIdentifier:kCellIdentifier] autorelease];
}
if (indexPath.row == 1)
{
cell.image = [UIImage imageNamed:#"foo.png"];
}
else if (indexPath.row == 2)
cell.image = [UIImage imageNamed:#"bar.png"];
}
...
else
{
cell.image = [UIImage imageNamed:#"lorem.png"];
}
return.cell;
}
A better approach then that if-else mess would be to push your images onto a NSMutableArray in the right order, and then just use
cell.image = [myImages objectAtIndex:indexPath.row];