UITableView

Multitouch
"I set cell.selectionStyle = UITableViewCellSelectionStyleNone because I don't want to use the standard selection view at all (it is limited to single rows). Instead, I achieve a selection color by creating a backgroundView for the cell and setting its background color to white or pale blue as appropriate. The selection indicator is just a UIImageView. As previously indicated, it is layed out 35 pixels left of the contentView which places it offscreen. When the contentView is shifted right during editing, it will become visible."
 * http://stackoverflow.com/questions/2046537/how-to-make-uitableviewcontroller-catch-multitouch-events
 * http://cocoawithlove.com/2009/01/multiple-row-selection-and-editing-in.html

General
[tableView reloadSections:[NSIndexSet indexSetWithIndex:0]] "You're supposed to wrap reloadSections in beginUpdates/endUpdates."
 * http://stackoverflow.com/questions/1369831/eliminate-extra-separators-below-uitableview-in-iphone-sdk
 * http://stackoverflow.com/questions/1362623/uitableview-is-loading-every-cell
 * http://forums.macrumors.com/showthread.php?t=830251

Snippets
self.tableView.allowsSelection = NO;

DELETE

 * http://stackoverflow.com/questions/3441953/how-to-display-red-cancel-button-in-uitableviewcell

Multi Row Selection

 * http://cocoawithlove.com/2009/01/multiple-row-selection-and-editing-in.html

Swiping
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath {  swipeEditingFlag = YES; [self setEditing:YES animated:YES]; }
 * http://forums.bignerdranch.com/viewtopic.php?f=55&t=152

- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath {  [self setEditing:NO animated:YES]; swipeEditingFlag = NO; }

Customizing UITableView section view

 * http://undefinedvalue.com/2009/08/25/changing-background-color-and-section-header-text-color-grouped-style-uitableview
 * 1) define SectionHeaderHeight 40

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { if ([self tableView:tableView titleForHeaderInSection:section] != nil) { return SectionHeaderHeight; }   else { // If no section header title, no section header needed return 0; } }

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { NSString *sectionTitle = [self tableView:tableView titleForHeaderInSection:section]; if (sectionTitle == nil) { return nil; }

// Create label with section title UILabel *label = [[[UILabel alloc] init] autorelease];   label.frame = CGRectMake(20, 6, 300, 30);    label.backgroundColor = [UIColor clearColor];    label.textColor = [UIColor colorWithHue:(136.0/360.0)  // Slightly bluish green                                 saturation:1.0                                 brightness:0.60                                      alpha:1.0];    label.shadowColor = [UIColor whiteColor];    label.shadowOffset = CGSizeMake(0.0, 1.0);    label.font = [UIFont boldSystemFontOfSize:16];    label.text = sectionTitle;

// Create header view and add label as a subview UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, SectionHeaderHeight)];   [view autorelease];    [view addSubview:label];

return view; }

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section // create the parent view that will hold header Label UIView* customView = [[[UIView alloc] initWithFrame:CGRectMake(10,0,300,60)] autorelease];
 * http://www.weask.us/entry/customize-tableview-section-view-iphone

// create image object UIImage *myImage = [UIImage imageNamed:@"someimage.png"];;

// create the label objects UILabel *headerLabel = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease]; headerLabel.backgroundColor = [UIColor clearColor]; headerLabel.font = [UIFont boldSystemFontOfSize:18]; headerLabel.frame = CGRectMake(70,18,200,20); headerLabel.text = @"Some Text"; headerLabel.textColor = [UIColor redColor];

UILabel *detailLabel = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease]; detailLabel.backgroundColor = [UIColor clearColor]; detailLabel.textColor = [UIColor darkGrayColor]; detailLabel.text = @"Some detail text"; detailLabel.font = [UIFont systemFontOfSize:12]; detailLabel.frame = CGRectMake(70,33,230,25);

// create the imageView with the image in it UIImageView *imageView = ; imageView.frame = CGRectMake(10,10,50,50);

[customView addSubview:imageView]; [customView addSubview:headerLabel]; [customView addSubview:detailLabel];

return customView;

Multiple Row Selection

 * http://cocoawithlove.com/2009/01/multiple-row-selection-and-editing-in.html

Recreating the UITableViewController

 * http://cocoawithlove.com/2009/03/recreating-uitableviewcontroller-to.html

Custom Drawing
// // CustomCellBackgroundView.h // // Created by Mike Akers on 11/21/08. // Copyright 2008 __MyCompanyName__. All rights reserved. //
 * http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html
 * http://pessoal.org/blog/2009/02/25/customizing-the-background-border-colors-of-a-uitableview/
 * http://stackoverflow.com/questions/898351/iphone-setting-background-on-uitableview
 * http://www.reigndesign.com/blog/liven-up-your-boring-uitableview-part-1/
 * http://www.iphonedevsdk.com/forum/iphone-sdk-development/1746-how-set-uitableview-background-image.html
 * http://www.roseindia.net/tutorial/iphone/examples/UITableViewBackgroundColor.html
 * https://github.com/sburlot/tableviewcellwithbkgnd
 * http://stackoverflow.com/questions/400965/how-to-customize-the-background-border-colors-of-a-grouped-table-view


 * 1) import 

typedef enum { CustomCellBackgroundViewPositionTop, CustomCellBackgroundViewPositionMiddle, CustomCellBackgroundViewPositionBottom, CustomCellBackgroundViewPositionSingle } CustomCellBackgroundViewPosition;

@interface CustomCellBackgroundView : UIView { UIColor *borderColor; UIColor *fillColor; CustomCellBackgroundViewPosition position; }

@property(nonatomic, retain) UIColor *borderColor, *fillColor; @property(nonatomic) CustomCellBackgroundViewPosition position; @end

// // CustomCellBackgroundView.m // // Created by Mike Akers on 11/21/08. // Copyright 2008 __MyCompanyName__. All rights reserved. //


 * 1) import "CustomCellBackgroundView.h"

static void addRoundedRectToPath(CGContextRef context, CGRect rect,                                                        float ovalWidth,float ovalHeight);

@implementation CustomCellBackgroundView @synthesize borderColor, fillColor, position;

- (BOOL) isOpaque { return NO; }

- (id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { // Initialization code }   return self; }

- (void)drawRect:(CGRect)rect { // Drawing code CGContextRef c = UIGraphicsGetCurrentContext; CGContextSetFillColorWithColor(c, [fillColor CGColor]); CGContextSetStrokeColorWithColor(c, [borderColor CGColor]);

if (position == CustomCellBackgroundViewPositionTop) { CGContextFillRect(c, CGRectMake(0.0f, rect.size.height - 10.0f, rect.size.width, 10.0f)); CGContextBeginPath(c); CGContextMoveToPoint(c, 0.0f, rect.size.height - 10.0f); CGContextAddLineToPoint(c, 0.0f, rect.size.height); CGContextAddLineToPoint(c, rect.size.width, rect.size.height); CGContextAddLineToPoint(c, rect.size.width, rect.size.height - 10.0f); CGContextStrokePath(c); CGContextClipToRect(c, CGRectMake(0.0f, 0.0f, rect.size.width, rect.size.height - 10.0f)); } else if (position == CustomCellBackgroundViewPositionBottom) { CGContextFillRect(c, CGRectMake(0.0f, 0.0f, rect.size.width, 10.0f)); CGContextBeginPath(c); CGContextMoveToPoint(c, 0.0f, 10.0f); CGContextAddLineToPoint(c, 0.0f, 0.0f); CGContextStrokePath(c); CGContextBeginPath(c); CGContextMoveToPoint(c, rect.size.width, 0.0f); CGContextAddLineToPoint(c, rect.size.width, 10.0f); CGContextStrokePath(c); CGContextClipToRect(c, CGRectMake(0.0f, 10.0f, rect.size.width, rect.size.height)); } else if (position == CustomCellBackgroundViewPositionMiddle) { CGContextFillRect(c, rect); CGContextBeginPath(c); CGContextMoveToPoint(c, 0.0f, 0.0f); CGContextAddLineToPoint(c, 0.0f, rect.size.height); CGContextAddLineToPoint(c, rect.size.width, rect.size.height); CGContextAddLineToPoint(c, rect.size.width, 0.0f); CGContextStrokePath(c); return; // no need to bother drawing rounded corners, so we return }

// At this point the clip rect is set to only draw the appropriate // corners, so we fill and stroke a rounded rect taking the entire rect

CGContextBeginPath(c); addRoundedRectToPath(c, rect, 10.0f, 10.0f); CGContextFillPath(c);

CGContextSetLineWidth(c, 1); CGContextBeginPath(c); addRoundedRectToPath(c, rect, 10.0f, 10.0f); CGContextStrokePath(c); }

- (void)dealloc { [borderColor release]; [fillColor release]; [super dealloc]; }

@end

static void addRoundedRectToPath(CGContextRef context, CGRect rect,                                                       float ovalWidth,float ovalHeight)

{   float fw, fh;

if (ovalWidth == 0 || ovalHeight == 0) {// 1 CGContextAddRect(context, rect); return; }

CGContextSaveGState(context);// 2

CGContextTranslateCTM (context, CGRectGetMinX(rect),// 3                                          CGRectGetMinY(rect)); CGContextScaleCTM (context, ovalWidth, ovalHeight);// 4 fw = CGRectGetWidth (rect) / ovalWidth;// 5 fh = CGRectGetHeight (rect) / ovalHeight;// 6

CGContextMoveToPoint(context, fw, fh/2); // 7 CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);// 8 CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);// 9 CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);// 10 CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); // 11 CGContextClosePath(context);// 12

CGContextRestoreGState(context);// 13 } ... with gradient instead of color // // CSCustomCellBackgroundView.h //


 * 1) import 

typedef enum {   CustomCellBackgroundViewPositionTop, CustomCellBackgroundViewPositionMiddle, CustomCellBackgroundViewPositionBottom, CustomCellBackgroundViewPositionSingle } CustomCellBackgroundViewPosition;

@interface CSCustomCellBackgroundView : UIView {   CustomCellBackgroundViewPosition position; CGGradientRef gradient; }

@property(nonatomic) CustomCellBackgroundViewPosition position;

@end

// // CSCustomCellBackgroundView.m //


 * 1) import "CSCustomCellBackgroundView.h"


 * 1) define ROUND_SIZE 10

static void addRoundedRectToPath(CGContextRef context, CGRect rect,        float ovalWidth,float ovalHeight);

@implementation CSCustomCellBackgroundView

@synthesize position;

- (BOOL) isOpaque {   return NO; }

- (id)initWithFrame:(CGRect)frame {   if (self = [super initWithFrame:frame]) {       // Initialization code const float* topCol = CGColorGetComponents([[UIColor redColor] CGColor]); const float* bottomCol = CGColorGetComponents([[UIColor blueColor] CGColor]);

CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB; /* CGFloat colors[] = {  5.0 / 255.0, 140.0 / 255.0, 245.0 / 255.0, 1.00,   1.0 / 255.0,  93.0 / 255.0, 230.0 / 255.0, 1.00,  };*/  CGFloat colors[]= {  topCol[0], topCol[1], topCol[2], topCol[3], bottomCol[0], bottomCol[1], bottomCol[2], bottomCol[3] }; gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4)); CGColorSpaceRelease(rgb); }   return self; }

-(void)drawRect:(CGRect)rect {   // Drawing code

CGContextRef c = UIGraphicsGetCurrentContext;

if (position == CustomCellBackgroundViewPositionTop) {

CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ; CGFloat miny = CGRectGetMinY(rect), maxy = CGRectGetMaxY(rect) ; minx = minx + 1; miny = miny + 1;

maxx = maxx - 1; maxy = maxy ;

CGContextMoveToPoint(c, minx, maxy); CGContextAddArcToPoint(c, minx, miny, midx, miny, ROUND_SIZE); CGContextAddArcToPoint(c, maxx, miny, maxx, maxy, ROUND_SIZE); CGContextAddLineToPoint(c, maxx, maxy);

// Close the path CGContextClosePath(c);

CGContextSaveGState(c); CGContextClip(c); CGContextDrawLinearGradient(c, gradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); CGContextRestoreGState(c);

return; } else if (position == CustomCellBackgroundViewPositionBottom) {

CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ; CGFloat miny = CGRectGetMinY(rect), maxy = CGRectGetMaxY(rect) ; minx = minx + 1; miny = miny + 1;

maxx = maxx - 1; maxy = maxy - 1;

CGContextMoveToPoint(c, minx, miny); CGContextAddArcToPoint(c, minx, maxy, midx, maxy, ROUND_SIZE); CGContextAddArcToPoint(c, maxx, maxy, maxx, miny, ROUND_SIZE); CGContextAddLineToPoint(c, maxx, miny); // Close the path CGContextClosePath(c);

CGContextSaveGState(c); CGContextClip(c); CGContextDrawLinearGradient(c, gradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); CGContextRestoreGState(c);

return; } else if (position == CustomCellBackgroundViewPositionMiddle) {       CGFloat minx = CGRectGetMinX(rect), maxx = CGRectGetMaxX(rect) ; CGFloat miny = CGRectGetMinY(rect), maxy = CGRectGetMaxY(rect) ; minx = minx + 1; miny = miny + 1;

maxx = maxx - 1; maxy = maxy ;

CGContextMoveToPoint(c, minx, miny); CGContextAddLineToPoint(c, maxx, miny); CGContextAddLineToPoint(c, maxx, maxy); CGContextAddLineToPoint(c, minx, maxy); // Close the path CGContextClosePath(c);

CGContextSaveGState(c); CGContextClip(c); CGContextDrawLinearGradient(c, gradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); CGContextRestoreGState(c);

return; } else if (position == CustomCellBackgroundViewPositionSingle) {       CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ; CGFloat miny = CGRectGetMinY(rect), midy = CGRectGetMidY(rect) , maxy = CGRectGetMaxY(rect) ; minx = minx + 1; miny = miny + 1;

maxx = maxx - 1; maxy = maxy - 1;

CGContextMoveToPoint(c, minx, midy); CGContextAddArcToPoint(c, minx, miny, midx, miny, ROUND_SIZE); CGContextAddArcToPoint(c, maxx, miny, maxx, midy, ROUND_SIZE); CGContextAddArcToPoint(c, maxx, maxy, midx, maxy, ROUND_SIZE); CGContextAddArcToPoint(c, minx, maxy, minx, midy, ROUND_SIZE); // Close the path CGContextClosePath(c);

CGContextSaveGState(c); CGContextClip(c); CGContextDrawLinearGradient(c, gradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); CGContextRestoreGState(c);

return; } }

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

- (void) setPosition:(CustomCellBackgroundViewPosition)inPosition { if(position != inPosition) { position = inPosition; [self setNeedsDisplay]; } }

@end

static void addRoundedRectToPath(CGContextRef context, CGRect rect,        float ovalWidth,float ovalHeight)

{   float fw, fh;

if (ovalWidth == 0 || ovalHeight == 0) {// 1 CGContextAddRect(context, rect); return; }

CGContextSaveGState(context);// 2

CGContextTranslateCTM (context, CGRectGetMinX(rect),// 3        CGRectGetMinY(rect)); CGContextScaleCTM (context, ovalWidth, ovalHeight);// 4 fw = CGRectGetWidth (rect) / ovalWidth;// 5 fh = CGRectGetHeight (rect) / ovalHeight;// 6

CGContextMoveToPoint(context, fw, fh/2); // 7 CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);// 8 CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);// 9 CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);// 10 CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); // 11 CGContextClosePath(context);// 12

CGContextRestoreGState(context);// 13 } ... fix corner problem -(void)drawRect:(CGRect)rect {   // Drawing code

CGContextRef c = UIGraphicsGetCurrentContext; CGContextSetFillColorWithColor(c, [fillColor CGColor]); CGContextSetStrokeColorWithColor(c, [borderColor CGColor]); CGContextSetLineWidth(c, 2);

if (position == CustomCellBackgroundViewPositionTop) {

CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ; CGFloat miny = CGRectGetMinY(rect), maxy = CGRectGetMaxY(rect) ; minx = minx + 1; miny = miny + 1;

maxx = maxx - 1; maxy = maxy ;

CGContextMoveToPoint(c, minx, maxy); CGContextAddArcToPoint(c, minx, miny, midx, miny, ROUND_SIZE); CGContextAddArcToPoint(c, maxx, miny, maxx, maxy, ROUND_SIZE); CGContextAddLineToPoint(c, maxx, maxy);

// Close the path CGContextClosePath(c); // Fill & stroke the path CGContextDrawPath(c, kCGPathFillStroke); return; } else if (position == CustomCellBackgroundViewPositionBottom) {

CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ; CGFloat miny = CGRectGetMinY(rect), maxy = CGRectGetMaxY(rect) ; minx = minx + 1; miny = miny ;

maxx = maxx - 1; maxy = maxy - 1;

CGContextMoveToPoint(c, minx, miny); CGContextAddArcToPoint(c, minx, maxy, midx, maxy, ROUND_SIZE); CGContextAddArcToPoint(c, maxx, maxy, maxx, miny, ROUND_SIZE); CGContextAddLineToPoint(c, maxx, miny); // Close the path CGContextClosePath(c); // Fill & stroke the path CGContextDrawPath(c, kCGPathFillStroke); return; } else if (position == CustomCellBackgroundViewPositionMiddle) { CGFloat minx = CGRectGetMinX(rect), maxx = CGRectGetMaxX(rect) ; CGFloat miny = CGRectGetMinY(rect), maxy = CGRectGetMaxY(rect) ; minx = minx + 1; miny = miny ;

maxx = maxx - 1; maxy = maxy ;

CGContextMoveToPoint(c, minx, miny); CGContextAddLineToPoint(c, maxx, miny); CGContextAddLineToPoint(c, maxx, maxy); CGContextAddLineToPoint(c, minx, maxy);

CGContextClosePath(c); // Fill & stroke the path CGContextDrawPath(c, kCGPathFillStroke); return; } } ... what if only one cell? else if (position == CustomCellBackgroundViewPositionSingle) {       CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ; CGFloat miny = CGRectGetMinY(rect), midy = CGRectGetMidY(rect) , maxy = CGRectGetMaxY(rect) ; minx = minx + 1; miny = miny + 1;

maxx = maxx - 1; maxy = maxy - 1;

CGContextMoveToPoint(c, minx, midy); CGContextAddArcToPoint(c, minx, miny, midx, miny, ROUND_SIZE); CGContextAddArcToPoint(c, maxx, miny, maxx, midy, ROUND_SIZE); CGContextAddArcToPoint(c, maxx, maxy, midx, maxy, ROUND_SIZE); CGContextAddArcToPoint(c, minx, maxy, minx, midy, ROUND_SIZE);

// Close the path CGContextClosePath(c); // Fill & stroke the path CGContextDrawPath(c, kCGPathFillStroke); return; }