In a UITableView Controller, I have just added 'swipe to delete' by implementing tableView: commitEditingStyle: forRowAtIndexPath
. Additionally, the rows can be selected to expand showing more content.
The undesired result after swiping:
The two lower rows remain in view after swiping until about about 0.5 seconds after the undelete animation completes.
A screenshot of IB:
The cell's contents have grown into the lower cell without it showing that it has been selected. (Selection causes the cell to increase height and give it a grayish background color.) This is occurring on every row in 2 similarly operating view controllers.
I have tried (without success) to intercept the 'selection' in several UITableViewDelegate methods, and cannot find out how to stop this from occurring. I have also tried setting the IB dynamic prototype cells to height: 85.
Looking for ideas on how to prevent this expansion from occurring.
EDIT
- (void)viewDidLoad { .... self.tableView.rowHeight = UITableViewAutomaticDimension; self.tableView.estimatedRowHeight = kCellHeight; .... } #pragma mark - TableView delegate - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return [[self.fetchedResultsController sections] count]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section]; NSInteger *rows = (NSInteger *)[sectionInfo numberOfObjects]; if (!self.rowsInSection) self.rowsInSection = rows; if (rows > 0) return [sectionInfo numberOfObjects]; else { [tableView setSeparatorColor:[UIColor clearColor]]; [tableView setBounces:NO]; return 1; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *identifier = self.rowsInSection > 0 ? @"numberIdentifier" : @"noNumbersIdentifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath]; if (self.rowsInSection > 0) [self configureCell:cell atIndexPath:indexPath]; else cell.selectionStyle = UITableViewCellSelectionStyleNone; // [self.arrayOfIndexPaths addObject:indexPath]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow]; if (selectedIndexPath) { if (tableView.editing) return 85.0; else if (selectedIndexPath.row == indexPath.row) return 185.0; } return 85.0; } - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)path { if (tableView.editing) return nil; // If real rows exist, return the path, making row selectable if (self.rowsInSection > 0) return path; // Otherwise do not allow the row to be selected return nil; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][0]; if ([sectionInfo numberOfObjects] > 0) // Return the contentView to stop the header from sliding with delete return [tableView dequeueReusableCellWithIdentifier:@"numberHeaderIdentifier"].contentView; else return [tableView dequeueReusableCellWithIdentifier:@"emptyHeaderIdentifier"]; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 75; } - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { Number *aNumber = [self.fetchedResultsController objectAtIndexPath:indexPath]; [cell configureSubviewsInCell:cell withNumber:aNumber]; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView beginUpdates]; [tableView endUpdates]; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]]; } }
2 Answers
Answers 1
You should set the hidden property of the labels that you don't want to show when the table view cell is not selected. For example:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { Number *aNumber = [self.fetchedResultsController objectAtIndexPath:indexPath]; UILabel *label1 = (UILabel *)[cell.contentView viewWithTag:501]; label1.text = [aNumber valueForKey:@"number"]; if (!cell.selected) { label1.hidden = YES; } else { label1.hidden = NO; } ..... }
Then in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView beginUpdates]; UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; UILabel *label1 = (UILabel *)[cell.contentView viewWithTag:501]; label1.text = [aNumber valueForKey:@"number"]; label1.hidden = NO; [tableView endUpdates]; }
You should look into subclassing UITableViewCell so you don't have to use tags to access subviews.
Answers 2
The 'hiding' solution posted by beowulf is a valid option. In addition and because the swipe (to begin editing) was causing subviews in the cell to become 'unclipped', a method needed to be overrided, like so:
// this method is called as the swipe to delete is started - (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(nonnull NSIndexPath *)indexPath { // only hide for unexpanded (unselected) cells if ([self.selectedRowIndex compare:indexPath] != NSOrderedSame) { NumberTableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; // a cell subclass method to hide/unhide subviews that fall into // the next cell below [cell subViewsInCellShouldBeHidden:YES]; } }
0 comments:
Post a Comment