Subclassing UITableViewCell to add image

Discussion in 'iOS Development' started by Chicken, May 21, 2009.

  1. Chicken

    Chicken Retired Moderator

    Joined:
    Feb 17, 2008
    Messages:
    2,494
    Likes Received:
    7
    Device:
    iPhone 5S
    I'm subclassing UITableViewCell to add an image to each cell. The problem I'm having is that the image is only visible when you click on the cell. Anyone know how to fix this? I can give code if you wish me to.
  2. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    That's because the selectedView is covering your image. Draw smarter.
  3. Chicken

    Chicken Retired Moderator

    Joined:
    Feb 17, 2008
    Messages:
    2,494
    Likes Received:
    7
    Device:
    iPhone 5S
    OK thanks. I'll go have a look.
    ------------------double post merged------------------
    Just for any other users that may come across this problem I used
    Code:
    [myContentView bringSubviewToFront:subview];
    and it fixes it
  4. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    Are you subclassing contentView? There's really no need to do that.
  5. gojohnnyboi

    gojohnnyboi Well-Known Member

    Joined:
    Jan 25, 2008
    Messages:
    3,339
    Likes Received:
    55
    The way I'm drawing these cells:

    Please Register or Log in to view images



    is subclassing UIView, and adding it to the cell's view, having it redraw every time the cell's frame changes (initial change when place in table), and when a highlight/selection occurs. I draw everything manually there, my strings, my images, and the CG lines that are there to look like AppStore's.


    EDIT: Look at Loren Brichtor's sample from Tweetie that he posted on his blog. It will show you. But drawing yourself makes it scroll incredibly fast.
  6. NolesFans

    NolesFans New Member

    Joined:
    Sep 23, 2008
    Messages:
    404
    Likes Received:
    0
    Device:
    iPod touch
    By Searching "Loren Brichtor" came out empty.

    Please Register or Log in to view images

  7. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    GJB, think harder. Adding views is adding memory, and is not optimal. You are on the right track by setting everything exclusive of drawing, and ONLY drawing with CG, limiting draw code only to drawRect. Also, drawing every time the frame changes (are you using setFrame:, like francis likes to do): I don't really like that. Mostly because of reusability, and animations suffer when doing that.

    Your best bet is to set frames in layoutSubviews: and draw in drawRect:. layoutSubviews: gets called when the cell is sent the -setNeedsLayout method (for example, when the cell enters editing mode, or when accessory controls appear. -setNeedsDisplay is then called after -setNeedsLayout, so your drawing will always happen correctly.

    Again, there is nothing wrong with what you're doing, but if you want to reuse your cells, especially in places where you may need to edit cells, your animations will not occur. See FlowChat for example.

    This is my base table cell subclass with nothing added, it simply draws the cell and colors it based on the .cellColor property I set. It also autodetects whether or not you are drawing a plain or grouped cell (and if so, the cell's location in the group), and draws appropriately.
    Code:
    - (void)drawRect:(CGRect)rect {
    	if (isGroupCell) {
    		[self drawGroupedCellRect:rect];
    	} else {
    		[self drawPlainCellRect:rect];
    	}
    }
    
    - (void)drawPlainCellRect:(CGRect)rect {
    	const CGFloat *clr = CGColorGetComponents(cellColor.CGColor);
    	
    	CGContextSetRGBFillColor(UIGraphicsGetCurrentContext(), clr[0], clr[1], clr[2], clr[3]);
    	CGContextMoveToPoint(UIGraphicsGetCurrentContext(), 0, 0);
    	CGContextAddLineToPoint(UIGraphicsGetCurrentContext(),self.frame.size.width , 0);
    	CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), self.frame.size.width, self.frame.size.height);
    	CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), 0, self.frame.size.height);
    	CGContextClosePath(UIGraphicsGetCurrentContext());
    	CGContextFillPath(UIGraphicsGetCurrentContext());
    	
    	if (drawsSeparator) {		
    		CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 1.0);
    		CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 1.0, 1.0, 0.8);
    		CGContextMoveToPoint(UIGraphicsGetCurrentContext(), 0, 0);
    		CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), rect.size.width, 0);
    		CGContextStrokePath(UIGraphicsGetCurrentContext());	
    		
    		CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.25, 0.25, 0.25, 0.8);
    		CGContextMoveToPoint(UIGraphicsGetCurrentContext(), 0, rect.size.height);
    		CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), rect.size.width, rect.size.height);
    		CGContextStrokePath(UIGraphicsGetCurrentContext());
    	}
    }
    And, in my subclass of that, I do all my subview arranging. I start by resizing the contentView so it doesn't cover the separators:
    Code:
    - (void)layoutSubviews {
    	[super layoutSubviews];
    	
    	self.contentView.frame = CGRectInset(self.contentView.frame, 0, 1);
    	CGRect rect = CGRectInset(self.contentView.bounds, 10, 9);		//Set to 9 to account for the 1px offset in the previous line.
    	textLabel.frame = rect;
    }
    That draws everything perfectly, and animates like butter. Also, scrolling is smooth as smooth, as smooth can be.

    To get cells as apparent in this screenshot:

    Please Register or Log in to view images


    To deal with selection, override:
    Code:
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    	[super setSelected:selected animated:animated];
    
    	/*	Your Code	*/
    
    }
    In the following screenshot, the selection is subtle. The selected cell is teh second cell, the one labeled "PocketTouch."

    Please Register or Log in to view images



    Clearly, I'm still toying around with colors, so ignore the color scheme for now.





    Side note, and hugely offtopic, you can also draw cells anyway you see fit. See the following two screenshots (second has a selected table cell). Note also, that I will be including these cells in my next iteration of PocketTouch.framework for everyone to be able to use them.

    Please Register or Log in to view images

    Please Register or Log in to view images








    EDIT: The point is, draw smarter, and try not to add objects if at all possible.
  8. gojohnnyboi

    gojohnnyboi Well-Known Member

    Joined:
    Jan 25, 2008
    Messages:
    3,339
    Likes Received:
    55
    @SkylarEC, correct me if I'm wrong. So, in your drawing method, you're basically setting your color, and then from what I'm seeing, filling the entire cell with that color, and then placing your separator lines where you want them. You're NOT adding another view to the cell. And then, obviously, for grouped tables, there is some arc additions that can be easily implemented.
  9. Steaps

    Steaps New Member

    Joined:
    Oct 24, 2007
    Messages:
    5,074
    Likes Received:
    41
    Device:
    iPod touch
  10. Cyanidepoison

    Cyanidepoison Active Member

    Joined:
    Jan 18, 2008
    Messages:
    1,076
    Likes Received:
    2
    So the idiot inside me wonders what colors those are and how you got them.

    I'm guessing it wasn't with [UIColor colorWithRed:green:blue] ?

Share This Page