views:

290

answers:

1

Hi,

I'm working on a UITableView whose cells contain an UIImageView subclass which gets data from a URL and cache images to the iphone disk.

Problem is, event with cached images the scrolling tends to be stuttering. So I searched a bit and found ABTableViewCell ( github.com/enormego/ABTableViewCell ) which is supposed to dramatically improve scrolling smoothness.

But, even with the example provided ( blog.atebits.com/2008/12/fast-scrolling-in-tweetie-with-uitableview ) I don't really get what I am supposed to do.

I tried to do this: I created a class which inherits ABTableViewCell, added some UILabels and the UIImageView as class properties, and implemented methods this way: allocate and initialize subviews (labels, image) in the initialize class method, storing them in static pointers, and then set class properties in - (void)drawContentView:(CGRect)r highlighted:(BOOL)highlighted along with background color setting shown in example. Here's the result:

static AsyncUIImageView* image = nil; // A subclass using ASIHTTPRequest for image loading
static UILabel*       label1 = nil;
static UILabel*       label2 = nil;

+ (void)initialize {
    if (self == [ResultTableViewCell class]) {
        image = [[[AsyncUIImageView alloc] initWithFrame:CGRectMake(0, 0, 80, 60)] retain];

        label1 = [[[UILabel alloc] initWithFrame:CGRectMake(90, 5, 150, 30)] retain];
        label1.font = [UIFont fontWithName:@"Helvetica-Bold" size:17];
        label1.textColor = [UIColor purpleColor];
        label1.backgroundColor = [UIColor clearColor];

        label2 = [[[UILabel alloc] initWithFrame:CGRectMake(180, 8, 100, 25)] retain];
        label2.font = [UIFont fontWithName:@"Helvetica-Bold" size:12.0];
        label2.textColor = [UIColor grayColor];
        label2.backgroundColor = [UIColor clearColor];
    }
}

- (void)drawContentView:(CGRect)r highlighted:(BOOL)highlighted {
    if (self.imageView == nil) {
        self.imageView = image;
        [self addSubview:image];

        self.firstLabel = label1;
        [self addSubview:label1];

        self.secondLabel = label2;
        [self addSubview:label2];
    }

CGContextRef context = UIGraphicsGetCurrentContext();

    UIColor *backgroundColor = [UIColor whiteColor];
    UIColor *textColor = [UIColor blackColor];

    if (self.selected || self.highlighted) {
        backgroundColor = [UIColor clearColor];
        textColor = [UIColor whiteColor];
    }

    [backgroundColor set];
    [textColor set];
    CGContextFillRect(context, r);      
}

This gives me completely black cells, sometimes one has text and image set with correct colors, but its content changes as I scroll down. Obviously I did not understand what I am supposed to do in drawContentView.

Could someone explain its purpose?

+1  A: 

The whole idea is to not add subviews, but to draw the text instead. Eg.

- (void)drawContentView:(CGRect)r highlighted:(BOOL)highlighted {

    [someText drawInRect:r withFont:aFont];
}
Tom Irving
Ok, I got it. Much clearer when explicitly said, thanks :)So I just stored NSStrings in place of labels and drew them manually. Two questions though:- What is the magic with [textColor set] and [backgroundColor set] which make them effectively change colors as they aren't class properties and their name can be changed? (at least for textColor)- And should I store as many items in static pointers as I can? Such as UIColors, CGPoints, CGRects?
Jukurrpa
1. The magic? 2. I don't think it should make much a difference, just do whatever is easiest.
Tom Irving
1. Well the fact that it influenced the color of drawings coming after. But I simply read the UIColor reference and got my response :)2. Okay, thanks.
Jukurrpa
Last question, I keep getting an EXC_BAD_ACCESS when I try to draw the image: [self.image drawInRect:CGRectMake(0, 0, 80, 60)]; . The image object seems ok according to gdb, what could cause this? I had to create it with "image = [UIImage imageWithCGImage:[newImage CGImage]]" in the setter, it has copy property.
Jukurrpa
You have to use "[self setImage:...]" or "self.image = ..."
Tom Irving
Well if I use self.image in the setter I'm getting a nice stack overflow as this makes the setter call himself.Maybe I my question wasn't clear enough, in the setter I do this: "image = [UIImage imageWithCGImage:[newImage CGImage]];", and in drawContentView I do this: "[self.image drawInRect:CGRectMake(0, 0, 80, 60)];"
Jukurrpa
Oh right, you need to throw a retain in there somewhere, otherwise it's being autoreleased and when you set a new UIImage, be sure to release the old one.
Tom Irving
Yup, that was the retain. It works perfectly now, though I don't understand what causes the release as the image property is copy and no release is done.Anyways thanks a lot for all your answers.
Jukurrpa
Because you're overriding the setter, the copy isn't actually happening. If you left it alone, it would probably look something like: [image release]; image = [newImage copy];
Tom Irving
Oh ok. I didn't know that properties only affect synthesized setters, thanks.
Jukurrpa