开发者

Drawing custom UITableCells with the correct data

I've got a UITableView with custom tablecells. First I had a version which implemented a separate NIB file to create the custom cell view, but this makes scrolling awfully slow. The official answer is to do your own drawing, so I implemented a drawing variant (ABTableViewCell).

Everything is working now, except for the drawing of the cells that are out of the view. The first 8 cells are drawn correctly - they get the correct title, image, etc. - but everything outside of that has a random repetition of already drawn cells. Only when the cell is clicked/touched the labels and images of the cell are updated with the correct data.

My RootViewController implements UITableViewDataSource and CustomCell is initialised there.

I've verified that all the data is passed correctly to the开发者_StackOverflow中文版 CustomCell, so it must have something to do with the drawing. I think I've tracked it down to the fact that the drawContentView method is only called for the cells which are in view and not for the ones that scroll into view.

How would I trigger the drawContentView again to update the cells which come into view? Is that something I would have to do from my RootViewController, using something else than: (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath?

CustomCell.h:

#import "ABTableViewCell.h"

@interface CustomCell : ABTableViewCell {
  NSString * cellSubText;
  NSString * cellText;
  NSString * cellImage;
  NSString * cellIcon;
  NSString * cellId;
}

@property (nonatomic, copy) NSString *cellSubText;
@property (nonatomic, copy) NSString *cellText;
@property (nonatomic, copy) NSString *cellImage;
@property (nonatomic, copy) NSString *cellIcon;
@property (nonatomic, copy) NSString *cellId;

@end

CustomCell.m:

#import "CustomCell.h"

@implementation CustomCell

@synthesize cellSubText, cellText, cellImage, cellIcon, cellId;

static UIFont *celSubFont = nil;
static UIFont *cellFont = nil;

+ (void)initialize {
    if(self == [CustomCell class]) {
        cellSubFont = [[UIFont systemFontOfSize:13] retain];
        cellFont = [[UIFont boldSystemFontOfSize:17] retain];
    }
}

- (void)setFirstText:(NSString *)s {
    [cellSubText release];
    cellSubText = [s copy];
    [self setNeedsDisplay]; 
}

- (void)setLastText:(NSString *)s {
    [cellText release];
    cellText = [s copy];
    [self setNeedsDisplay]; 
}

- (void)drawContentView:(CGRect)r {
    CGContextRef context = UIGraphicsGetCurrentContext();

    UIColor *backgroundColour = [UIColor whiteColor];
    UIColor *categoryColour = [UIColor grayColor];
    UIColor *titleColour = [UIColor blackColor];
  if(self.highlighted || self.selected) {
    backgroundColour = [UIColor clearColor];
        categoryColour = [UIColor whiteColor];
    titleColour = [UIColor whiteColor];
    }

    [backgroundColour set];
    CGContextFillRect(context, r);

    CGPoint pCategory;
    pCategory.x = 60;
    pCategory.y = 3;

    [categoryColour set];
  [cellSubText drawAtPoint:pCategory forWidth:235 withFont:categoryFont minFontSize:13 actualFontSize:NULL lineBreakMode:UILineBreakModeTailTruncation baselineAdjustment:UIBaselineAdjustmentNone];  

  CGPoint pTitle;
    pTitle.x = 60;
    pTitle.y = 17;

  [titleColour set];
  [cellText drawAtPoint:pTitle forWidth:235 withFont:titleFont minFontSize:17 actualFontSize:NULL lineBreakMode:UILineBreakModeTailTruncation baselineAdjustment:UIBaselineAdjustmentNone];  

  //Display the image
  CGPoint pImage;
    pImage.x = 5;
    pImage.y = 5;

  NSData *imageData = [[NSData dataWithContentsOfURL:[NSURL URLWithString:cellImage]] retain];
  UIImage *image = [UIImage imageWithData:imageData];
  [image drawAtPoint:pImage];
}

- (void)dealloc {
  [cellSubText release];
  [cellText release];
  [cellIcon release];
  [cellImage release];
  [super dealloc];
}
@end

RootViewController.m

#import "CustomCell.h"
#import "MyAppDelegate.h"
#import "RootViewController.h"
#import "DetailViewController.h"

@implementation RootViewController
@synthesize tableDataArray;

- (void)viewDidLoad {
  [super viewDidLoad];
}

//Override the default initWithNibName method
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil tableDataSource:(NSArray*)tableData {
  if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
    // Custom initialization
    tableDataArray = [tableData retain];   
  }
  return self;
}

-(void)viewWillAppear:(BOOL)animated {
  appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];    
  [super viewWillAppear:animated];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  return [self.tableDataArray count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CustomCellIdentifier = @"CustomCellIdentifier";

    CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CustomCellIdentifier];
    if(cell == nil) {
        cell = [[[CustomCell alloc] initWithFrame:CGRectZero reuseIdentifier:CustomCellIdentifier] retain];
    }
  cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
  NSUInteger row = [indexPath row];
  NSDictionary *rowData = [self.tableDataArray objectAtIndex:row];
    cell.cellSubText = [rowData objectForKey:@"Date"];
    cell.cellText = [rowData objectForKey:@"Name"];
  cell.cellImage = [rowData objectForKey:@"Image"];
  cell.cellId = [rowData objectForKey:@"Id"];

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
  NSString *selectedCell = [tableDataArray objectAtIndex:indexPath.row];

  DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailView" bundle:[NSBundle mainBundle]];
  detailViewController.selectedCell = selectedCell;
  [self.navigationController pushViewController:detailViewController animated:YES];
  [detailViewController release];
  detailViewController = nil;
}

- (void)dealloc { 
    [super dealloc];
}

@end


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CustomCellIdentifier = @"CustomCellIdentifier";

    CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CustomCellIdentifier];
    if(cell == nil) {
        cell = [[[CustomCell alloc] initWithFrame:CGRectZero reuseIdentifier:CustomCellIdentifier] retain];
    }

static NSString *CustomCellIdentifier = @"CustomCellIdentifier";

The above bolded code is making such behavior for you.

In iphone, tableview reuses already created cells. which are not visible. Ex: First 8 cells will be created separately. And when you scroll down, first few rows will get hide. Now the hidden cells are going to be reused by the cells which are going to show now. This is why you are getting this behavior:) Try to give unique identifier if your table view contents are less.

or

If your cell is a subclass of UITableViewCell, you can override

- (void)prepareForReuse

which gets called just before the cell is returned from

- (UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier


Perhaps the table view is reusing your cells and giving you random results by reusing the currently setup cells; have you looked into - (void)prepareForReuse on the UITableViewCell class?


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int myButtonTag = 1000+(10*indexPath.section)+indexPath.row;
    NSString *kCellID = [NSString stringWithFormat:@"cellId_%i",myButtonTag];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
    if (cell == nil)
    {
       //[[cell viewWithTag:myButtonTag] removeFromSuperview];
       cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID];
    }

    cell.accessoryType = UITableViewCellAccessoryNone;
}

In order to remove data from your cell while scrolling fast in a UITableView (especially in an ARC controlled environment), do remember to set a Unique CellIdentifier in your cellId string, which dequeues the older cell. This way it exempts it from populating the repeated cells. Hope you find it appropriate and to your liking. Cheers!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜