views:

349

answers:

1

I have a a UITableView with cells that are partially custom using addSubview. I am using a different cell ID for the last cell, whose purpose is to load more data from a server which will make new cells appear. (Think the "Load more messages from server" cell in Mail.app)

E.g.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // <... code for normal cells omitted...>
    static NSString *LoadMoreCellIdentifier = @"LoadMoreCellIdentifier";

    UILabel *loadMoreLabel;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:LoadMoreCellIdentifier];

    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:LoadMoreCellIdentifier] autorelease];

        cell.selectionStyle = UITableViewCellSelectionStyleGray;

        loadMoreLabel = [[[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, cell.frame.size.width, self.tableView.rowHeight - 1)] autorelease];
        loadMoreLabel.tag = LOAD_MORE_TAG;
        loadMoreLabel.font = [UIFont boldSystemFontOfSize:16.0];
        loadMoreLabel.textColor = [UIColor colorWithRed:0.153 green:0.337 blue:0.714 alpha:1.0]; // Apple's "Load More Messages" font color in Mail.app
        loadMoreLabel.textAlignment = UITextAlignmentCenter;
        [cell.contentView addSubview:loadMoreLabel];
    }
    else
    {
        loadMoreLabel = (UILabel *)[cell.contentView viewWithTag:LOAD_MORE_TAG];
    }

    loadMoreLabel.text = [NSString stringWithFormat:@"Load Next %d Hours...", _defaultHoursQuery];
    return cell;
}

As you can see above, I set cell.selectionStyle = UITableViewCellSelectionStyleGray;

When you tap on a cell, I clear the selection like so:

-       (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{   
    if (_showLoadMoreEntriesButton && indexPath.row == [_sourceArray count])
    {
         // <... omitted...>
         // Do a potentially blocking 1 second operation here to obtain data for more
         // cells. This will potentially change the size of the _sourceArray 
         // NSArray that acts as the source for my UITableCell
         [tableView deselectRowAtIndexPath:indexPath animated:NO];

         [self.tableView reloadData];
         return;
    }

    [tableView deselectRowAtIndexPath:indexPath animated:NO];
    [self _loadDataSetAtIndex:indexPath.row];
}

The problem I'm seeing is that I have to tap and hold my finger down to have the gray highlight appear. If I tap very quickly, it doesn't display draw a highlight at all. The problem being that sometimes I perform an blocking operation that will take a second or so. I want some simple UI feedback that something is happening, instead of the UI just locking up. I think this may be related to me conditionally checking for if the indexPath is the last row of the table or not.

Any idea how to get it to draw the highlight every time?

+1  A: 

If possible, move your blocking operation to another thread. NSOperation is probably a good system to use.

There's no clean way to tell the UI thread to process anything while you're in the middle of a blocking operation.

John Calsbeek
I don't want it to process anything, I just want the cell selection to always show. I understand it will be non-responsive.
Jeremy
If your code is blocking on the main thread, then any processing that the UI thread needs to do to update and respond to user input won't happen, and there's not really a way around that besides using threads.
John Calsbeek
That's a good point. I suppose I should try something asynchronous.
Jeremy
To see if this was the problem, I completely removed the blocking code. All I do now is deselect the row. Even so, the highlight does not draw if i touch very quickly. It seems to draw properly on my other "normal" unique cell identifiers but not on my "Load More" cell, that I've posted the code for above. Any other ideas? I appreciate your advice.
Jeremy