带有自定义单元格子视图的 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