更新uitableview时断言失败

Posted

技术标签:

【中文标题】更新uitableview时断言失败【英文标题】:Assertion Failure when updating uitableview 【发布时间】:2013-08-02 00:40:25 【问题描述】:

我在单击节标题时尝试更新我的表格视图时收到此断言。

* -[UITableView _endCellAnimationsWithContext:] 中的断言失败,/SourceCache/UIKit_Sim/UIKit-2839.5/UITableView.m:1264

我只是想在单击节标题视图时隐藏和显示自定义单元格。

如果我用重新加载数据替换更新代码,代码工作正常。但这并不顺利:(

- (void)noteSectionHeader:(UTNoteSectionHeader *)noteSectionHeader sectionTapped:(NSInteger)section

    UTNoteItem* noteItem = self.notes[section];
    BOOL alreadySelected = noteItem.selected;
    if (alreadySelected) 
        self.selectedSection = NSNotFound;
        [self setSelected:NO forSection:section];
    
    else 
        self.selectedSection = section;
        [self setSelected:YES forSection:section];
    

    [self updateSections];


- (void)setSelected:(BOOL)selected forSection:(NSInteger)section

    UTNoteItem* noteItem = self.notes[section];
    noteItem.selected = selected;
    for (UTNoteItem* tmpItem in self.notes) 
        if (tmpItem != noteItem) 
            tmpItem.selected = NO;
        
    


- (void)updateSections

    NSMutableArray* deletePaths = [[NSMutableArray alloc] init];
    NSMutableArray* addPaths = [[NSMutableArray alloc] init];


    for (UTNoteItem* item in self.notes) 
        if (item.selected) 
            [addPaths addObject:[NSIndexPath indexPathForRow:0 inSection:[self.notes indexOfObject:item]]];
        
        else 
            [deletePaths addObject:[NSIndexPath indexPathForRow:0 inSection:[self.notes indexOfObject:item]]];
        
    

    [self.tableView beginUpdates];
    [self.tableView deleteRowsAtIndexPaths:deletePaths withRowAnimation:YES];
    [self.tableView insertRowsAtIndexPaths:addPaths withRowAnimation:YES];
    [self.tableView endUpdates];




#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    return self.notes.count;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    UTNoteItem* itemNote = self.notes[section];
    if (itemNote.selected) return 1;
    return 0;


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

    return 40;

编辑:

这是我的新实现:

-

 (void)noteSectionHeader:(UTNoteSectionHeader *)noteSectionHeader sectionTapped:(NSInteger)section

    /* Check if a section is opened */
    if (self.selectedSection != NSNotFound) 
        /* A section is open, get the item */
        UTNoteItem* theItem = self.notes[self.selectedSection];
        /* if the item is the section opened, close it */
        if (self.selectedSection == section) 
            theItem.selected = NO;
            self.selectedSection = NSNotFound;

        
        /* The item is not the section, so open it, and close the previous item */
        else 
            theItem.selected = YES;
            UTNoteItem* prevItem = self.notes[self.selectedSection];
            prevItem.selected = NO;
            self.selectedSection = section;
        
    
    /* Nothin is open, just open the section */
    else 
        self.selectedSection = section;
        UTNoteItem* openItem = self.notes[self.selectedSection];
        openItem.selected = YES;
    
    /* Reload the selected section.. this will not reload the other sections? */
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationAutomatic];

【问题讨论】:

【参考方案1】:

我遇到了类似的问题,但是我执行了这样的重新加载:

- (void)noteSectionHeader:(UTNoteSectionHeader *)noteSectionHeader sectionTapped:(NSInteger)section
 
        //check our action
        if(<will hide section>) 
            //hide section
            <some action>
         else 
             //show section
             <some action>
        
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationAutomatic];
    

它会通过强制更新再次以不同的方式重新加载:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    NSInteger nRows = 0; //no rows when closed

    if(<check section is open>) 
        nRows +=<number of data items shown>;
    

    return nRows;

indexpath.section 是我希望隐藏或显示的部分。它光滑稳定。 在我看来,删除和添加行有点危险,tableviews 非常擅长对单个部分或单元格进行动画重新加载。

【讨论】:

我实际上不使用行作为“标题”。我使用部分作为我的主要标题。所以我的行数是 0,直到一个部分被点击。那么它应该是 1(现在) 那么请进行相应的调整。逻辑是一样的。如果不可见,您的部分将有 0 行,并且单击事件将是 - (void)noteSectionHeader:(UTNoteSectionHeader *)noteSectionHeader sectionTapped:(NSInteger)section 我已调整答案以更符合您的情况,如果有帮助请告诉我; 在第一次点击时工作,当我点击另一个部分时它再次失败:( 你在修改数据吗?您是否删除了所有添加和删除行的调用?

以上是关于更新uitableview时断言失败的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 的“尝试删除部分”断言失败

具有多个 NSFetchedResultsControllers 的 UITableView 导致断言失败

尝试从 UITableView 中删除行时断言失败

UITableView CoreData 断言失败

应用程序退出 *** -[UITableView _configureCellForDisplay:forIndexPath:] 中的断言失败

> -[UITableView dequeueReusableCellWithIdentifier:forIndexPath:] 中的断言失败