Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hiding UITableViewCell

Is there a way to hide a UITableView cell? I'm looking for some property or method I can invoke on the UITableViewCell returned by a synchronous cellForRowAtIndexPath() to hide it and make it unselectable by the user.

like image 216
live2dream95 Avatar asked Apr 19 '10 20:04

live2dream95


5 Answers

For me using mapping is not easy way, so I decided to use SAS method. But it doesn't work with my custom cell. So, I correct it:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.row == 7 && hide7Row){
        UITableViewCell* cell = [cells objectAtIndex:indexPath.row];
        cell.hidden = YES;
        return 0.0;
    }
    else if(indexPath.row == 8 && hide8Row){
        UITableViewCell* cell = [cells objectAtIndex:indexPath.row];
        cell.hidden = YES;
        return 0.0;
    }
    else {
        return 44.0;
    }
}

Works Fine.

like image 107
HotJard Avatar answered Oct 18 '22 22:10

HotJard


You mean to leave a gap in the table where the cell should be, or just to progress from the one before it straight to the one after it? In the former case, I guess you might try getting the cell's contentView and set its hidden property to YES; otherwise, you'll just have to do a little logic in your -tableView:numberOfRowsInSection: and -tableView:cellForRowAtIndexPath: methods, returning (the number of cells you'd otherwise return - 1) from the first, and, depending on whether the row index is less than or greater than the row you're not including, either (the cell you'd otherwise return) or (the cell at (the row index + 1)), respectively.

(edit, because the explanation was convoluted:)

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
    if(section == theSectionWithoutARow)
    {
        if(shouldRemoveTheRow)
            return [theArrayWithTheSectionContents count] - 1;
        else
            return [theArrayWithTheSectionContents count];
    }
    // other sections, whatever
}

- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // blah blah standard table cell creation

    id theCellObject;

    if(indexPath.section == theSectionWithoutARow)
    {
        NSInteger theActualRowToDisplay = indexPath.row;
        if(shouldRemoveTheRow && indexPath.row >= theRowIndexToRemove)
        {
            theActualRowToDisplay = indexPath.row + 1;
        }
        theCellObject = [theArrayWithTheSectionContents objectAtIndex:theActualRowToDisplay];
    }

    // now set up the cell with theCellObject

    return cell;
}
like image 40
Noah Witherspoon Avatar answered Oct 18 '22 23:10

Noah Witherspoon


There is no method to do that on the cellForRowAtIndexPath as far as I am aware.

Noah Witherspoon's method seems to be more or less workable, although it will need to be modified if you want multiple rows to be hidden.

Another way to approach it is to create a "cell map", I don't know if this is more efficient or not, but I've used it and it worked.

Let us say you have an NSArray (or mutable version thereof) of data which is to be shown in your TableView. The array's count property is used as the return value for your numberOfRowsInSection delegate method. This is a somewhat typical approach to my knowledge.

To make it so that only some of the rows are shown, I created a "mapping array", which is an NSMutableArray that contains "pointers" to your actual data array. The map contains integers wrapped in NSNumbers. In its virgin state the map's index 0 has the integer 0 (wrapped in NSNumber), index 1 has integer 1, etc.

The UITableView delegate methods are built so that the map's index count is used for numberOfRowsInSection. In the cellForRowAtIndexPath method, it looks at the appropriate index of the map array, retrieves whatever is wrapped in the NSNumber, and then looks in that index of your actual data array.

The benefit of this dereference is that it becomes extremely easy to add and remove cells from the table. Just add/remove the NSNumber objects from your mapping array. Make sense? Sorry, not at my Mac or I could just put up some code samples.

Oh, and don't forget that you have to call the update method (the exact name escapes me) on your TableView so that it refreshes and the cells hide/unhide.

like image 28
Matt Mc Avatar answered Oct 19 '22 00:10

Matt Mc


Had the same problem, and as I wanted to avoid some mapping as mentioned, I just set the cell-size to 0:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    NSInteger row=[indexPath row];
    float ret=0.0;

    if( row==3) {
        ret=0.0;
    }
    else {
        ret=40.0;
    }
    return ret;
}
like image 2
SAS Avatar answered Oct 18 '22 22:10

SAS


I used Matt's technique to create a mapping to cell data. Here is some code:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return computeNumberOfRowsAndMapCellData;
}

// Compute mapToCellData to map the index of the cell to the cell data for the 
// cell based on TaskConfig show/hide.
// Return the number of rows in section 1.
- (NSInteger)computeNumberOfRowsAndMapCellData {
    if (mapToCellData) {
        [mapToCellData release];
    }
    mapToCellData =[[NSMutableArray alloc] init];
    if (cellData) {
        [cellData release];
    }
    cellData = [[NSMutableArray alloc] init];

    NSInteger numberOfRows = 12;  // maximum number of rows
    NSNumber *index = [NSNumber numberWithInt:0];

    // If the data is not configured to show, decrement the number of rows in the table. 
    if ( ! [configManager isShowDateForType:task.case_type severity:task.severity]) {
        numberOfRows--;
    } else {
        // Add a map to the cell data with the row number.
        NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[df stringFromDate:task.respond_due_date], @"Respond Due", nil];
        [cellData addObject:dict];
        [mapToCellData addObject:index];
        int value = [index intValue];
        index = [NSNumber numberWithInt:value + 1];
    }
    // Check the configuration for the rest of the rows of cell data.
    ....
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];        
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
        cell.textLabel.numberOfLines = 0;
        cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
        cell.textLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:15];
        cell.detailTextLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:14];
    }

    NSUInteger mapIndex = 0;

    // Use the mapToCellData to find cell data based on show/hide in ConfigManager for the data type.
    mapIndex = [indexPath row];
    NSNumber *cellDataIndex = [mapToCellData objectAtIndex:mapIndex];
    NSDictionary *cellDataDict = [cellData objectAtIndex:[cellDataIndex unsignedIntegerValue]]; 
    cell.textLabel.text = = [[cellDataDict allValues] objectAtIndex:0];
    cell.detailTextLabel.text = [[cellDataDict allKeys] objectAtIndex:0];
like image 1
Andy in Boulder Avatar answered Oct 18 '22 23:10

Andy in Boulder