Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reloadData VS. reloadRowsAtIndexPaths

My question is as the title suggests. There's a difference between the two methods on iOS 7/iPhone 4. The thing is I'm loading chat conversation in a bubble chat form. Each cell is a bubble containing the text msg, the date and the msg status (sent, received, seen or incoming).

When I need to reload a specific cell, I use the method reloadRowsAtIndexPaths method. It works just perfect on iOS 8 (iPhone 4s and iPhone 5c). However, it does not on iOS 7 (iPhone 4). By "work" I mean it reloads just ok. But with the iOS 7 case, it only loads the background view without loading the text or any other elements.

Obviously, this means the data upon reloading is find (because it did work on other devices). I need to use reloadData after reloadRowsAtIndexPaths to get the whole thing loaded in iOS 7 (iPhone 4). Or, I should scroll the table view to get the cell loaded.

I did work the problem out. But I want to know if that's a known bug in iPhone 4 (iOS 7).

Here's a piece of the code that might be helpful understanding the problem:

- (void)tableView:(UIBubbleTableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell * cell = [self.bubbleTable cellForRowAtIndexPath:indexPath];
    if ([cell isKindOfClass:[UIBubbleTableViewCell class]] && isEditing) {
        NSBubbleData * bubble;
        // fetch the corresponding bubble index in the bubble data array
        int bubbleIndex = [self getArrayIndexForIndexPath:indexPath];
        bubble = [self.bubbleData objectAtIndex:bubbleIndex];
        // making sure it's either a msg sent by me or msg sent by someone else. In other words, making sure it's neither a system message nor is it a header date or something.
        if (bubble.type != BubbleTypeMine && bubble.type != BubbleTypeSomeoneElse)
            return;

        // configure the bubble to be [de]selected
        bubble.isSelected = !bubble.isSelected;

        // add the Key-Value pair to the dictionary
        if ([selectedIndices valueForKey:bubble.msgID]) [selectedIndices removeObjectForKey:bubble.msgID];
        else [selectedIndices setValue:[NSNumber numberWithInt:bubbleIndex] forKey:bubble.msgID];

        // update gui
        [self.bubbleTable reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationMiddle];
        if([[self machineName] isEqualToString:@"iPhone3,1"] ||
           [[self machineName] isEqualToString:@"iPhone3,2"] ||
           [[self machineName] isEqualToString:@"iPhone3,3"]) { // iphone 4
            [self.bubbleTable reloadData];
        }
#if DEBUG
        printf("Selected Message Text: %s\n", [[[_anasDb getFromChatRoom:self.contactInternationalPhone message:bubble.msgID] valueForKey:MESSAGE_TEXT] UTF8String]);
#endif
    }
}

Clearly, you don't have to get every bit of it. Here's what the code is saying (in the context of the question):

  1. Fetch instance of the cell.
  2. Edit some of its properties so it would behave differently after next reloading
  3. Reload that particular cell using reloadRowsAtIndexPaths- which works on every device so far except iPhone 4 (iOS 7) which needs reloadData.

Here's the relevant part of the cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UIBubbleTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
    NSBubbleData *data = [[self.bubbleSection objectAtIndex:indexPath.section] objectAtIndex:indexPath.row - 1];

    if (cell == nil) cell = [[UIBubbleTableViewCell alloc] init];

    cell.data = data;
    cell.showAvatar = self.showAvatars;
    if (data.isSelected) {
        cell.dim = YES;
        cell.backgroundColor = [UIColor colorWithRed:0.0 green:0.39 blue:0.106 alpha:0.2f];
    } else {
        cell.backgroundColor = [UIColor clearColor];
    }
    return cell;

Thanks in advance.

like image 982
joker Avatar asked Nov 01 '22 09:11

joker


1 Answers

Problem with your code is that u need load data to cell inside

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

Inside - (void)tableView:(UIBubbleTableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath adjust your data then call reloadRowsAtIndexPaths for specified rows. Do not change cell labels inside that method (or u can change both data and cell content here if u don't want to reload specific rows)

Reload data reloads all rows which is not what u need in most cases as it stops scrolling and recomputes heights, sections count, etc

like image 78
Aleksey Mazurenko Avatar answered Nov 02 '22 22:11

Aleksey Mazurenko