3

TL:DR 版本:我使用 NSZombieEnabled 来查找 EXC_BAD_ACCESS 错误的来源,并看到一个库的发布比保留多 1 个。我可以假设这个库导致崩溃还是该版本与另一个库的保留相关联?

我在我的应用程序中遇到了一些问题,UITableViewCell 子类实例在其保留计数达到 0 后收到消息。我使用 NSZombies 运行应用程序,目前正在尝试配对保留/释放调用以查找错误的确切来源。我注意到只有 2 个保留和 3 个版本将“责任库”设置为 QuartzCore。这是否意味着额外的发布调用是导致我的应用程序崩溃的原因?或者一个版本是否有可能在另一个库中关联了保留?

附加信息:我的部分标题是可点击的,当一个被选中时,这个部分的行被插入到表格视图中,并且任何以前可见的行都被删除。换句话说,一次只能有 1 个部分有 1 行,所有其他部分必须有 0 行。

我配对的来自 QuartzCore 的释放/保留调用是:

CALayer layoutSublayers    (retains)
CA::Layer::layout_if_needed(CA::Transaction*)    (releases)

没有一对的版本是:

CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*)

我遇到崩溃的确切行是 endUpdates 行:

- (void)sectionHeaderView:(SectionHeaderView *)sectionHeaderView sectionOpened:(NSInteger)sectionOpened {

    SectionInfo *sectionInfo = [self.sectionInfoArray objectAtIndex:sectionOpened];

    sectionInfo.open = YES;

    NSMutableArray *indexPathsToInsert = [[NSMutableArray alloc] init];

    [indexPathsToInsert addObject:[NSIndexPath indexPathForRow:0 inSection:sectionOpened]];


    /*
     Create an array containing the index paths of the rows to delete: These correspond to the rows for each quotation in the previously-open section, if there was one.
     */
    NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];

    NSInteger previousOpenSectionIndex = self.openSectionIndex;
    if (previousOpenSectionIndex != NSNotFound) {

        SectionInfo *previousOpenSection = [self.sectionInfoArray objectAtIndex:previousOpenSectionIndex];
        previousOpenSection.open = NO;
        previousOpenSection.category.model = nil;
        [previousOpenSection.headerView toggleOpenWithUserAction:NO];

        [indexPathsToDelete addObject:[NSIndexPath indexPathForRow:0 inSection:previousOpenSectionIndex]];

    }


    // Style the animation so that there's a smooth flow in either direction.
    UITableViewRowAnimation insertAnimation;
    UITableViewRowAnimation deleteAnimation;
    if (previousOpenSectionIndex == NSNotFound || sectionOpened < previousOpenSectionIndex) {
        insertAnimation = UITableViewRowAnimationTop;
        deleteAnimation = UITableViewRowAnimationBottom;
    }
    else {
        insertAnimation = UITableViewRowAnimationBottom;
        deleteAnimation = UITableViewRowAnimationTop;
    }

    NSIndexPath *indexToDelete = [indexPathsToDelete firstObject], *indexToInsert = [indexPathsToInsert firstObject];
    if (indexToDelete == nil) {
        NSLog(@"no row to delete");
    }
    else {
        NSLog(@"deleting row %d section %d", [indexToDelete row], [indexToDelete section]);
    }
    NSLog(@"inserting row %d section %d", [indexToInsert row], [indexToInsert section]);

    // Apply the updates.
    [self.tableView beginUpdates];
    [self.tableView insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:insertAnimation];
    [self.tableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:deleteAnimation];
    [self.tableView endUpdates];  // this is the crash.

    self.openSectionIndex = sectionOpened;


    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:sectionOpened] atScrollPosition:UITableViewScrollPositionNone animated:YES];

}

该错误发生在 iOS7 上。

4

2 回答 2

0

如果数组中的索引路径无效(例如 的节号),您可以EXC_BAD_ACCESS在该行获得 a 。您应该使用and并确保它们具有有效值。endUpdates-1NSLogindexPathsToInsertindexPathsToDelete

于 2013-09-25T11:20:38.263 回答
0

我已经找到了解决这个问题的方法。似乎在异步请求结束后,表格单元格的子视图之一正在调用 becomeFirstResponder。当然,如果牢房在那一刻已经被释放,那么崩溃就发生了。起初我只是假设问题是由于保留和释放的不平衡,但看起来不是这样。

并回答标题中的问题:当与 NSZombieEnabled Instruments 一起运行时,应用程序已经配对了一些保留/释放,当它可以假设它们已连接时。在我的应用程序的一次运行中,Instruments 加入了来自 QuartzCore 的发布与来自 UIKit 的保留。尽管我不能 100% 确定它是正确的,但我认为“责任库”标签相同不是强制性的。

TL:DR - 我很确定保留可以与来自另一个库的发布配对。

于 2013-09-26T15:41:04.913 回答