Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Have you considered using 4 separate cell identifiers for the "lonely, "top", "bottom", and "middle" cases and setting the <code>backgroundView</code> only once when initializing the cell? Doing it that way lets you leverage <code>UITableView</code>'s own caching and reuse without having to write an implementation on top of it.</p> <hr> <p><strong>Update</strong>: An implementation for a grouped <code>UITableViewController</code> subclass that reuses background views with a minimal number of cell reuse identifiers (Espresso's use case). <code>tableView:willDisplayCell:forRowAtIndexPath:</code> and <code>tableView:didDisplayCell:forRowAtIndexPath:</code> do the heavy lifting to apply or reclaim each background view, and the pooling logic is handled in <code>backgroundViewForStyle:</code>.</p> <pre><code>typedef NS_ENUM(NSInteger, JSCellBackgroundStyle) { JSCellBackgroundStyleTop = 0, JSCellBackgroundStyleMiddle, JSCellBackgroundStyleBottom, JSCellBackgroundStyleSolitary }; @implementation JSMasterViewController { NSArray *backgroundViewPool; } - (void)viewDidLoad { [super viewDidLoad]; // these mutable arrays will be indexed by JSCellBackgroundStyle values backgroundViewPool = @[[NSMutableArray array], // for JSCellBackgroundStyleTop [NSMutableArray array], // for JSCellBackgroundStyleMiddle [NSMutableArray array], // for JSCellBackgroundStyleBottom [NSMutableArray array]]; // for JSCellBackgroundStyleSolitary } #pragma mark - Table View - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 5; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == 2) { return 1; } else if (section == 3) { return 0; } return 5; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSInteger section = indexPath.section; NSInteger row = indexPath.row; static NSString *switchCellIdentifier = @"switchCell"; static NSString *textFieldCellIdentifier = @"fieldCell"; static NSString *textCellIdentifier = @"textCell"; UITableViewCell *cell = nil; // apply a cached cell type (you would use your own logic to choose types of course) if (row % 3 == 0) { cell = [tableView dequeueReusableCellWithIdentifier:switchCellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:switchCellIdentifier]; UISwitch *someSwitch = [[UISwitch alloc] init]; cell.accessoryView = someSwitch; cell.textLabel.text = @"Switch Cell"; } } else if (row % 3 == 1) { cell = [tableView dequeueReusableCellWithIdentifier:textFieldCellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:textFieldCellIdentifier]; UITextField *someField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 80, 30)]; someField.borderStyle = UITextBorderStyleRoundedRect; cell.accessoryView = someField; cell.textLabel.text = @"Field Cell"; } } else { cell = [tableView dequeueReusableCellWithIdentifier:textCellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:textCellIdentifier]; cell.textLabel.text = @"Generic Label Cell"; } } cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.textLabel.backgroundColor = [UIColor clearColor]; cell.detailTextLabel.text = [NSString stringWithFormat:@"[%d, %d]", section, row]; cell.detailTextLabel.backgroundColor = [UIColor clearColor]; return cell; } - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { // apply a cached background view JSCellBackgroundStyle backgroundStyle = [self backgroundStyleForIndexPath:indexPath tableView:tableView]; cell.backgroundView = [self backgroundViewForStyle:backgroundStyle]; } - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { JSCellBackgroundStyle backgroundStyle = [self backgroundStyleForIndexPath:indexPath tableView:tableView]; NSMutableArray *stylePool = backgroundViewPool[backgroundStyle]; // reclaim the background view for the reuse pool [cell.backgroundView removeFromSuperview]; if (cell.backgroundView != nil) { [stylePool addObject:cell.backgroundView]; } cell.backgroundView = nil; // omitting this line will cause some rows to appear without a background because they try to be in two superviews at once } - (JSCellBackgroundStyle)backgroundStyleForIndexPath:(NSIndexPath*)indexPath tableView:(UITableView*)tableView { NSInteger maxRow = MAX(0, [tableView numberOfRowsInSection:indexPath.section] - 1); // catch the case of a section with 0 rows if (maxRow == 0) { return JSCellBackgroundStyleSolitary; } else if (indexPath.row == 0) { return JSCellBackgroundStyleTop; } else if (indexPath.row == maxRow) { return JSCellBackgroundStyleBottom; } else { return JSCellBackgroundStyleMiddle; } } - (UIView*)backgroundViewForStyle:(JSCellBackgroundStyle)style { NSMutableArray *stylePool = backgroundViewPool[style]; // if we have a reusable view available, remove it from the pool and return it if ([stylePool count] &gt; 0) { UIView *reusableView = stylePool[0]; [stylePool removeObject:reusableView]; return reusableView; // if we don't have any reusable views, make a new one and return it } else { UIView *newView = [[UIView alloc] init]; NSLog(@"Created a new view for style %i", style); switch (style) { case JSCellBackgroundStyleTop: newView.backgroundColor = [UIColor blueColor]; break; case JSCellBackgroundStyleMiddle: newView.backgroundColor = [UIColor greenColor]; break; case JSCellBackgroundStyleBottom: newView.backgroundColor = [UIColor yellowColor]; break; case JSCellBackgroundStyleSolitary: newView.backgroundColor = [UIColor redColor]; break; } return newView; } } @end </code></pre> <p>Although you could very easily get away with dumping all views into one reuse pool, it complicates some of the looping logic and this way is easier to comprehend.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload