【问题标题】:"EXC_BAD_ACCESS" error when cell begins scrolling back in view?当单元格开始在视图中回滚时出现“EXC_BAD_ACCESS”错误?
【发布时间】:2010-11-12 00:33:58
【问题描述】:

我有一些(我认为)非常基本的代码,用于从数据源创建单元格内容,并且在显示加载时一切正常。但是,当我开始滚动查看其他文本(向上或向下)时,代码失败并显示“GDB:程序接收信号:“EXEC_BAD_ACCESS”。这是填充各个部分的显示的代码;每个部分都有类似的代码:

id cell = (UITableViewCell *)[tableView
    dequeueReusableCellWithIdentifier:CellIdentifier
];

titledCell = [[[TitledCell alloc]
          initWithFrame:CGRectZero
        reuseIdentifier:CellIdentifier
    ] autorelease
];

switch (tableSection) {
    case TABLE_SECTION_1:
        if (cell == nil) {
            dataKey = @"a key from data source";
            dataFromSource = [viewData objectForKey:dataKey];

            titledCell.title.text = dataKey;
            titledCell.contents.text = dataFromSource;
            cell = titledCell;
            break;
        }
    case TABLE_SECTION_2:        
    ...
}
return cell;

当我跟踪代码时,我注意到当将单元格滚动回视图时,代码会跳过单元格创建,因为单元格!= nil。如果它跳过,这意味着单元格包含与第一次创建时相同的内容,对吗?为什么给我找麻烦?

【问题讨论】:

  • 检查调试器窗口和控制台会有帮助
  • 您应该真正遵循您在 iPhone 和 Mac OS X 示例代码中看到的规范 Objective-C 编码风格;它将使您的代码更容易被其他人阅读并帮助您。
  • 好点,克里斯,我已经改变了一点——虽然我对规范的 Objective-C 风格不是很熟悉,所以它可能不太正确。我会努力的。

标签: objective-c iphone exception


【解决方案1】:

当我忘记保留某些内容时,我通常会收到EXEC_BAD_ACCESS。如果你有一个 autorelased 对象,它可能第一次可以工作,但第二次不能工作。

通过调试运行程序并使用 Xcode 找出它在哪一行崩溃。这将比其他任何事情都更有帮助。

【讨论】:

  • 这很笼统,我知道它是对的,所以你得到了信任!我希望我有原始代码来验证它有什么问题。
【解决方案2】:

我认为 EXEC_BAD_ACCESS 可能是由以下原因引起的:

titledCell.title.text = dataKey;

titledCell 可能会被释放,并且在访问该属性时会出现 EXEC_BAD_ACCESS 异常。

您可以在以下位置打开 NSZombieEnabled env virable:Group & Files -> Extutables -> Your App -> Get Info -> Arguments

【讨论】:

  • 抱歉使这个答案无关紧要的编辑(我在您发布答案时对其进行了编辑;我开始调查这种可能性并发现真正的问题是什么,所以我用所有相关代码更新了这个问题. 无论如何感谢您的帮助!+1 因为这是我发布的代码的“最佳猜测”!
  • 实际上,让我修改一下:我不明白这个问题。在我看来,代码应该可以工作,因为单元格引用了与 titledCell 相同的内存空间。结果应该只是清空内容吧?
  • 我很乐意将此标记为答案。我很确定你写下的那一行确实是导致崩溃的那一行——此外,我喜欢 Zombies :P 不幸的是,我无法进行任何测试来确定它是否正确,所以我只能投票给你上一个。
【解决方案3】:

不能 100% 确定您给出的代码示例,但一个很好的猜测是 break 语句位于 if 块中。所以它应该是这样的:

switch( tableSection ) {
    case TABLE_SECTION_1:
            if( cell == nil ) {
                    dataKey = @"a key from data source";
                    dataFromSource = [ viewData objectForKey:dataKey ];

                    titledCell.title.text = dataKey;
                    titledCell.contents.text = dataFromSource;
                    cell = titledCell;
            }
            break;
    case TABLE_SECTION_2:        
    ...
}

【讨论】:

    【解决方案4】:

    不幸的是,变化使这个问题变得学术化,所以我真的无法判断给出的任何答案是否正确。当前的代码看起来更接近于这个:

     id cell = (UITableViewCell *)[tableView
          dequeueReusableCellWithIdentifier:CellIdentifier
     ];
    
     if (cell == nil) {
          titledCell = [[[TitledCell alloc]
                       initWithFrame:CGRectZero
                     reuseIdentifier:CellIdentifier
               ] autorelease
          ];
    
          switch (tableSection) {
               case TABLE_SECTION_1:
                    dataKey = @"a key from data source";
                    dataFromSource = [viewData objectForKey:dataKey];
    
                    titledCell.title.text = dataKey;
                    titledCell.contents.text = dataFromSource;
                    cell = titledCell;
                    break;
               case TABLE_SECTION_2:
               ...
     }
     return cell;
    

    ...所以大部分代码现在都在“if (cell == nil)”块中(这更有意义),并且工作正常。我希望我明白出了什么问题,但无论如何感谢您的回答!

    【讨论】:

    • 我对 Objective-C 更加熟悉了,所以我现在知道当您尝试向已释放的对象发送消息时确实会发生 EXEC_BAD_ACCESS,所以我将标记最佳答案在这里作为“答案”。
    猜你喜欢
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    相关资源
    最近更新 更多