Not sure how to delete UITableViewCells that are grouped in sections

Discussion in 'iOS Programming' started by webznz, Apr 12, 2011.

  1. macrumors member

    Joined:
    Mar 8, 2011
    Location:
    Hobbitin
    #1
    Hi, I have implemented a UITableView with grouped style. in that table view their are two sections one section i have stopped it from being edited but the other rows are fine, i have an edit button and swipe to delete for these however because of the way i have set up tableView:cellForRowAtIndexPath: with different sections and row I think its stopping my rows from being deletable.

    here is the code, and error message when I try to delete a cell.. if you have any suggestions on what im doing wrong that would be helpful.

    Code:
    #pragma mark -
    #pragma mark Table view data source
    
    // Customize the number of sections in the table view.
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return 2;
    }
    
    //This method adds headings to my sections
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
        NSString *title = nil;
        // Return a title or nil as appropriate for the section.
        switch (section) {
            case SEARCH_SECTION:
                title = @"Search";
                break;
            case ADVANCED_SECTION:
                title = @"Advanced Search";
                break;
            default:
                break;
        }
        return title;;
    }
    
    
    // Customize the number of rows in the table view.
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        NSInteger rows = 0;
        /*
         The number of rows depends on the section.
         In the case of ADVANCE_SECTION, if editing, add a row in editing mode to present an "Add ????" cell.
    	 */
        switch (section) {
            case SEARCH_SECTION:
                rows = 2;
                break;
            case ADVANCED_SECTION:
    			rows = 1;
    
                break;
    		default:
                break;
        }
        return rows;
    }
    
    
    
    // Customize the appearance of table view cells.
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    	
        if (indexPath.section == 0) {
    		if (indexPath.row == 0) {
    			return cellCode;			
    		}
    		if (indexPath.row == 1) {
    			return cellManufacture;
    		}
            if (indexPath.row == 2) {
    			return cellModel;
    		}
        }
    	return cellYear;	
    }
    
    
    // Override to support conditional editing of the table view.
    - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
        // Return NO if you do not want the specified item to be editable.
    	if (indexPath.section == 0) {
    		if (indexPath.row == 0) {
    			return NO;
    		}
    		if (indexPath.row == 1) {
    			return NO;
    		}
    	}
        return YES;
    }
    
    
    // Override to support editing the table view. tableView:commitEditingStyle:forRowAtIndexPath:
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    
        if (editingStyle == UITableViewCellEditingStyleDelete) {
            // Delete the row from the data source.
    		[self resignFirstResponder];
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        }   
        else if (editingStyle == UITableViewCellEditingStyleInsert) {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
        }   
    }
    
    
    /*
    // Override to support rearranging the table view.
    - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
    }
    */
    
    
    /*
    // Override to support conditional rearranging of the table view.
    - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
        // Return NO if you do not want the item to be re-orderable.
        return YES;
    }
    */
    
    
    log

    Code:
    
    [Session started at 2011-04-13 11:06:41 +1200.]
    2011-04-13 11:06:48.950 instaCode1.2[1395:207] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1447.6.4/UITableView.m:976
    2011-04-13 11:06:48.953 instaCode1.2[1395:207] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 1.  The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted).'
    *** Call stack at first throw:
    (
    	0   CoreFoundation                      0x00db0be9 __exceptionPreprocess + 185
    	1   libobjc.A.dylib                     0x00f055c2 objc_exception_throw + 47
    	2   CoreFoundation                      0x00d69628 +[NSException raise:format:arguments:] + 136
    	3   Foundation                          0x000b447b -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
    	4   UIKit                               0x00336a0f -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] + 8424
    	5   UIKit                               0x00325f43 -[UITableView deleteRowsAtIndexPaths:withRowAnimation:] + 56
    	6   instaCode1.2                        0x00002756 -[RootViewController tableView:commitEditingStyle:forRowAtIndexPath:] + 117
    	7   UIKit                               0x003232ea -[UITableView(UITableViewInternal) animateDeletionOfRowWithCell:] + 101
    	8   UIKit                               0x002b9a6e -[UIApplication sendAction:to:from:forEvent:] + 119
    	9   UIKit                               0x003481b5 -[UIControl sendAction:to:forEvent:] + 67
    	10  UIKit                               0x0034a647 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
    	11  UIKit                               0x003491f4 -[UIControl touchesEnded:withEvent:] + 458
    	12  UIKit                               0x002de0d1 -[UIWindow _sendTouchesForEvent:] + 567
    	13  UIKit                               0x002bf37a -[UIApplication sendEvent:] + 447
    	14  UIKit                               0x002c4732 _UIApplicationHandleEvent + 7576
    	15  GraphicsServices                    0x016e6a36 PurpleEventCallback + 1550
    	16  CoreFoundation                      0x00d92064 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
    	17  CoreFoundation                      0x00cf26f7 __CFRunLoopDoSource1 + 215
    	18  CoreFoundation                      0x00cef983 __CFRunLoopRun + 979
    	19  CoreFoundation                      0x00cef240 CFRunLoopRunSpecific + 208
    	20  CoreFoundation                      0x00cef161 CFRunLoopRunInMode + 97
    	21  GraphicsServices                    0x016e5268 GSEventRunModal + 217
    	22  GraphicsServices                    0x016e532d GSEventRun + 115
    	23  UIKit                               0x002c842e UIApplicationMain + 1160
    	24  instaCode1.2                        0x0000207c main + 102
    	25  instaCode1.2                        0x0000200d start + 53
    )
    terminate called after throwing an instance of 'NSException'
    
    
     
  2. macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #2
    Read the description of the assertion failure carefully:

    When you call deleteRowsAtIndexPaths: the table does some sanity checking. It calls your methods for numberOfSections and numberOfRowsInSections and checks if the new number of sections and rows matches the old numbers plus your changes. In your case you hard code the number of sections and number of rows so after you tell the table that you've deleted a row your data model still has the same number of rows. That doesn't make any sense. 1 - 1 != 1;
     
  3. thread starter macrumors member

    Joined:
    Mar 8, 2011
    Location:
    Hobbitin
    #3
    yea, would the best solution for the tableView:numberOfRowsInSection: be to set up a global variable that catches a increment from each row in tableView:cellForRowAtIndexPath: ? or is there a more efficent way of doing this?
     
  4. macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #4
    The usual way to do this is to have a data model that represents the data in the table. So a section is usually represented by an array of dictionaries. When the user deletes a row the code removes that dictionary from the array. The code in rowsForSection returns the number of items in the array, not a hard-coded number.
     
  5. thread starter macrumors member

    Joined:
    Mar 8, 2011
    Location:
    Hobbitin
    #5
    Cool, thanks for the tip.. will look into it now,once I figure it out ill post my solution...
     

Share This Page