带有自定义单元格子视图的 UITableView - respondsToSelector:]:消息发送到已释放的实例

Posted

技术标签:

【中文标题】带有自定义单元格子视图的 UITableView - respondsToSelector:]:消息发送到已释放的实例【英文标题】:UITableView with custom cell subview - respondsToSelector:]: message sent to deallocated instance 【发布时间】:2011-02-09 15:04:04 【问题描述】:

我有一个包含 UITableView 的 ViewController,其中的单元格是通过自定义子视图创建的(这样每个单元格都会有一个标签和文本字段)。子视图包括在 textFieldDidBeginEditing、textFieldDidEndEditing 等上触发的 TextField 委托方法。UITableView 缓存可见的单元格,并在单元格不再可见时销毁它们。我遇到的问题是,当用户点击单元格中的 TextField 然后滚动表格以使正在“编辑”的单元格不在视野中,然后点击新单元格进行编辑时,原始单元格的 textFieldDidEndEditing 委托方法是调用,导致“respondsToSelector:]: message sent to deallocated instance”错误,因为当 UITableView 滚动出可见区域时,原始/第一个 TextField 已被销毁。

之前有没有人处理过这个问题并找到了解决方案,这样我就可以保留我的 textFieldDidEndEditing 方法来正确处理用户输入的数据,而不会破坏现在不可见的单元格?

编辑:我刚刚在 UITableView 类参考文档中找到了这一点:“避免重新布局内容。当重用具有自定义子视图的单元格时,请避免在每次表格视图请求单元格时布置这些子视图。布置子视图一次,何时创建单元格。”

我认为这是我问题的根源。但我不确定如何遵循这个建议。帮助...

【问题讨论】:

您最终找到解决方案了吗? 我发现在我的情况下,只是没有在 nib 中指定重用标识符导致单元格的释放,ios6 可以原谅这一点,但 ios7 不会 【参考方案1】:

“UITableView 缓存可见的单元格,并在单元格不再可见时销毁它们。”仅当您不提供重用标识符时才会如此。

假设您正在处理详细视图,其中每个单元格都呈现(至少在概念上)某个模型对象的属性,您可以为每个单元格分配一个唯一的重用标识符。您可以直接在 Interface Builder 中进行设置,或者,如果您以编程方式创建单元格,则可以将其作为参数传递给 initWithStyle:reuseIdentifier:initWithFrame:reuseIdentifier

给定一个重用标识符,表格视图将在其整个生命周期内缓存单元格。要从缓存中获取单元格,请使用

cell = [tableView dequeueReusableCellWithIdentifier:@"Some Identifier You Made Up"];

同样,如有必要,使用不同的标识符来区分唯一的单元格。

对于具有固定数量的唯一单元格的详细视图,另一种方法是将对每个单元格的引用存储在实例变量中(或将它们的整个组存储在集合中)。只要您保留实例变量,即使您不费心提供重用标识符,也不会释放单元格。

【讨论】:

事后看来,我认为我的“编辑:”实际上把水弄混了......在尝试了几件事之后,我认为这个问题与通过标识符重用单元格没有任何关系。它与离开屏幕时释放的单元格有关。你看,那时,当用户点击不同的单元格时,仍然会调用 TextField 委托方法“textFieldDidEndEditing”(其中包含不同的 TextField 实例......但是TextField 已被释放,导致错误。有什么建议吗? 我在发布之前没有看到您的编辑,所以我正在解决您的原始问题。如果您希望我更具体,我需要查看您的代码。 我很欣赏那个 jlehr。不幸的是,在这种情况下,我将不得不发布如此多的代码,以至于我的公司完全适合。我将看看我是否可以创建一个新的测试应用程序来重现问题,如果可以,我会发布它供您检查。非常感谢您的帮助! 我不需要看你的代码,但我想知道你是否真的理解我的帖子。如果遵循我的任何一个建议,单元格及其内容将不会被释放,并且您将不会遇到您所描述的问题。你试过吗?到目前为止,您还没有提供任何详细信息,所以我不得不猜测您是在呈现列表视图还是详细视图。是这样吗?【参考方案2】:

我想知道这是否是您的问题:

if (cell == nil) 
    // dont do this -->cell = [[[customCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];


    NSArray *topLevelsObjects = [[NSBundle mainBundle] loadNibNamed:@"NewUserCustomCell" owner:nil options:nil];
    for (id currentObject in topLevelsObjects)
        if ([currentObject  isKindOfClass:[UITableViewCell class]])
            cell = (customCell *) currentObject;
            break;
        
    

【讨论】:

【参考方案3】:

我不知道您是否找到了解决方案。但是我遇到了同样的问题,我通过在我的自定义字段的 dealloc 中将文本字段的委托设置为 nil 来修复它,然后再释放它。这样,就不会在释放的单元格上调用委托 textFieldDidEndEditing。 我也没有使用重用标识符。

- (void)dealloc 
  [textField_ setDelegate:nil];
  [textField_ release];
  [super dealloc];

【讨论】:

以上是关于带有自定义单元格子视图的 UITableView - respondsToSelector:]:消息发送到已释放的实例的主要内容,如果未能解决你的问题,请参考以下文章

带有自定义单元格的 UITableView 弹出窗口失败,单元格属性始终为零

iOS - 带有自定义单元格的可点击 UITableView

需要 AutoLayout UITableView 自定义单元格解决方案

一个 UIViewController 中的自定义单元格 tableview 和默认 UITableView

带有多个自定义单元格的“UITableView 无法从其数据源获取单元格”

使用 Auto Layout 创建具有多个不同自定义单元格的 UITableView 具有几乎相同的子视图