Why do my table view cells disappear when reloaded using reloadRowsAtIndexPaths?

后端 未结 12 1771
青春惊慌失措
青春惊慌失措 2021-02-02 12:20

I have a bare-bones sample project here:

http://dl.dropbox.com/u/7834263/ExpandingCells.zip

In this project, a UITableView has a custom UITableViewCell. In each

相关标签:
12条回答
  • 2021-02-02 12:40

    I just downloaded your project & found this section of code in didSelectRowAtIndexPath delegate where reloadRowsAtIndexPaths is used.

    [tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationAutomatic];
    [tableView beginUpdates];
    [tableView endUpdates];
    

    instead of the above why don't you try this?

    [tableView beginUpdates];
    [tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationAutomatic];
    [tableView endUpdates];
    

    The reason i am suggesting this is that I believe reloadRowsAtIndexPaths:... only works when wrapped inbetween calls to:

    - (void)beginUpdates;
    - (void)endUpdates;
    

    Outside of that, behavior is undefined and as you've discovered, fairly unreliable. Quoting relevant part of "Table View Programming Guide for iPhone OS":

    To animate a batch insertion and deletion of rows and sections, call the insertion and deletion methods within an animation block defined by successive calls to beginUpdates and endUpdates. If you don’t call the insertion and deletion methods within this block, row and section indexes may be invalid. beginUpdates...endUpdates blocks are not nestable.

    At the conclusion of a block—that is, after endUpdates returns—the table view queries its data source and delegate as usual for row and section data. Thus the collection objects backing the table view should be updated to reflect the new or removed rows or sections.

    The reloadSections:withRowAnimation: and reloadRowsAtIndexPaths:withRowAnimation: methods, which were introduced in iPhone OS 3.0, are related to the methods discussed above. They allow you to request the table view to reload the data for specific sections and rows instead of loading the entire visible table view by calling reloadData.

    There could be other valid reason but let me mull on this a bit, since i have your code too I could muck around with it. Hopefully we should figure it out...

    0 讨论(0)
  • 2021-02-02 12:41

    Short, pragmatic answer: Changing UITableViewRowAnimationAutomatic to UITableViewRowAnimationTop solves the issue. No more disappearing rows! (tested on iOS 5.1)

    Another short, pragmatic answer, since UITableViewRowAnimationTop is said to cause its own issues: Create a new cell view instead of modifying the existing one's frame. In a real app the data displayed in the cell view is supposed to be in the Model part of the app anyway, so if properly designed it shouldn't be a problem to create another cell view which displays the same data only in a different manner (frame in our case).

    Some more thoughts regarding animating the reload of the same cell:

    UITableViewRowAnimationAutomatic seems to resolve to UITableViewRowAnimationFade in some cases, which is when you see the cells fading away and disappearing. The new cell is supposed to fade in while the old one fades out. But here the old cell and the new one are one and the same - So, could this even work? In the Core Animation level, Is it possible to fade out a view AND fade it in at the same time? Sounds dubious. So the result is that you just see the fade out. This could be considered an Apple bug, since an expected behavior could be that if the same view has changed, the alpha property wouldn't be animated (since it can't animate both to 0 and to 1 at the same time), but instead just the frame, color etc. would be animated.

    Note the problem is just in the animation's display - if you scroll away and back, everything will appear correctly.

    In iOS 4.3 the Automatic mode might have been resolved to something other than Fade which is why things work there (as you write they do) - I didn't dig into that.

    I don't know why iOS chooses the Fade mode when it does. But one of the cases it does is when your code asks reloads a previously tapped cell, which is collapsed, and is different than the current tapped cell. Note the previously tapped cell is always reloaded, this line in your code is always called:

    [indicesToReload addObject:[previousIndexPath_ copy]];
    

    This explains the magic disappearing cells scenario you have described.

    By the way, the beginUpdates/endUpdates seem like a hack to me. This pair of calls is just supposed to contain animations, and there aren't any animations you are adding in addition to the rows you already asked to reload. All it did in this case is magically cause the Automatic mode to not choose Fade in some cases - But this just obscured the problem.

    A final note: I played around with the Top mode and found it can also cause problems. For example plugging the following code makes cells disappear funkily:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
    }
    

    Not sure if there is a real issue here (similar to the one with fading a view in and out at the same time), or maybe an Apple bug.

    0 讨论(0)
  • 2021-02-02 12:44

    The cell that is fading out is the previous cell that is not changing size. As the documentation of reloadRowsAtIndexPaths:withRowAnimation: states:

    The table animates that new cell in as it animates the old row out.

    What happens is the opacity is set to 1 then immediately set to 0 and so it fades out.

    If both the previous and the new cell change size then it works as intended. This is because the begin/end Updates notice the height changes and create new animations on those cells overriding the reloadRowsAtIndexPaths:withRowAnimation: ones.

    Your problem is due to abusing reloadRowsAtIndexPaths:withRowAnimation: to resize the cells when it's intended for loading new cells.

    But you don't need reloadRowsAtIndexPaths:withRowAnimation: at all. Just change the expanded state of the cells and do the begin/end updates. That will handle all the animation for you.

    As a side note I found the blue selection a little annoying, in JVCell set the selectedBackgroundView to the same image as the backgroundView (or create a new image that has the correct look of a selected cell).


    EDIT:

    Move the statement adding previousIndexPath_ to indicesToReload to the if statement (at line 132) so that it is only added if the previous cell was expanded and needs to resize.

    if( expanded ) {
        [previousCell setExpanded:NO];
        [indicesToReload addObject:[previousIndexPath_ copy]];
    }
    

    This removes the case where the previous collapsed cell would disappear.

    Another option would be to set previousIndexPath_ to nil when the current cell is collapsed and only set it when a cell expands.

    This still feels like a hack. Doing both the reloadRows and the begin/end Updates causes the tableView to reload everything twice but both seem to be needed to animate correctly. I suppose if the table is not too large this won't be a performance problem.

    0 讨论(0)
  • 2021-02-02 12:45

    To animate the height changes of a tableView just call.

    [tableView beginUpdates];
    [tableView endUpdates];
    

    Don't call reloadRowsAtIndexPaths:

    See Can you animate a height change on a UITableViewCell when selected?

    0 讨论(0)
  • 2021-02-02 12:46

    When you use this method, you have to be sure that you are on the main thread. Refreshing a UITableViewCell as follow should do the trick :

    - (void) refreshTableViewCell:(NSNumber *)row
    {
        if (![[NSThread currentThread] isMainThread])
        {
            [self performSelector:_cmd onThread:[NSThread mainThread]  withObject:row waitUntilDone:NO];
            return;
        }
    
        /*Refresh your cell here
         ...
         */
    
    }
    
    0 讨论(0)
  • 2021-02-02 12:51

    Try this hope it will help u Cell Expansion

    0 讨论(0)
提交回复
热议问题