UITableView 数据源方法的奇怪行为

Posted

技术标签:

【中文标题】UITableView 数据源方法的奇怪行为【英文标题】:Weird behavior of UITableView data source methods 【发布时间】:2013-12-06 18:12:21 【问题描述】:

我想创建一个具有标准 tableview 数据源方法(-cellForRowAtIndexPath:-numberOfRows 等)的默认实现的 UIViewController 类。

我想创建一个自定义下拉列表。

这是我的问题的详细说明: 我定义了MyDropDownListController 类,它实现了UITableViewDelegateUITableViewDataSource 协议,其中UITableView ivar 称为table

然后,我定义一个自定义的配置方法:

-(void)initDropDownListWithItems:(NSArray*)items andAddToView:(UIView*)view

    dropDownItems = items; //data source array of items to display in list
    table = [[UITableView alloc] initWithFrame: CGRectMake(view.frame.origin.x, view.frame.origin.y + view.frame.size.height + 1, view.frame.size.width, 140)];
    [view addSubview:table]; //add my table to view
    [table setDataSource:self];
    [table setDelegate:self];
    [table reloadData];
 

然后我定义-numberOfRowsInSection:cellForRowAtIndexPath等 在此之后,在其他一些 UIViewController 类中(我想要我的下拉列表)我有这个:

dataSource = @[@"first", @"second", @"third"];
MyDropDownListController * list= [[MyDropDownListController alloc] init];
[list initDropDownListWithItems:dataSource andAddToView:someViewInThisController];

启动应用程序后,显示此列表时出现奇怪的异常,例如:

-[_UIParallaxDimmingView tableView:numberOfRowsInSection:]:无法识别的选择器发送到实例 0x16500c70

如您所见,MyDropDownListController 并没有调用数据源方法,而是为其他一些奇怪的事情调用了数据源方法。

这些消息可能会有些不同:

[UIBarButtonItem tableView:numberOfRowsInSection:]: 无法识别 发送选择器

等等。

希望您能看到问题所在。 正如我在这里所说的那样,MyDropDownListController 似乎没有调用数据源方法:

[table setDataSource:self];

但对于其他一些东西。

【问题讨论】:

您能否在代码中的某个位置再次设置表的数据源?是否在MyDropDownListController 中实现了所需的数据源方法? @BlackRider 不,我只是在这个initDropDown 方法中第一次设置它们。是的,我说过Then I define numberOfRowsInSection: and cellForRowAtIndexPath and etc. 很奇怪。 [table reloadData] 内部的 initDropDownListWithItems 调用是否成功? @BlackRider 这个问题即使我不​​打电话[table reloadData] @BlackRider 我从帖子中删除了这个电话,以免误导。正如我所理解的那样,这些方法中的自我问题?因为代替它的方法接收者是一些其他未知对象 【参考方案1】:

我的猜测是,将表作为类变量的视图控制器正在被释放,因为它的引用计数在函数末尾为 0。当您执行以下操作时:


dataSource = @[@"first", @"second", @"third"];
MyDropDownListController * list= [[MyDropDownListController alloc] init];
[list initDropDownListWithItems:dataSource andAddToView:someViewInThisController];

在函数 ARC 结束时,如果内存不再被任何东西引用,则将其标记为可重用。您将控制器引用为 tableview 的委托,但委托是弱引用,不计入 ARC。所以你得到无法识别的选择器的原因是因为ARC标记了内存位置以供重用,然后操作系统通过在那里放置新对象来重用它。然后您的表将其称为委托(由于操作系统重新填充内存,它仍然是一个有效对象)并且您收到一个无法识别的选择器错误。如果您在发生这种情况时没有创建对象,那么您将收到bad access 错误,该错误可以通过 NSZombies 进行跟踪。

【讨论】:

谢谢。但我不明白你的意思是什么:“类变量”?在 Objective-C 中,我只知道类方法。可能你的意思是局部变量? @interface 中定义的变量(无论是属性还是iVar)都是类变量(至少在我的命名法中)。在函数(方法)中定义的任何东西都是局部变量(局部意味着它将在函数结束时消失)。

以上是关于UITableView 数据源方法的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

水平滚动 UITableView 的奇怪行为(在 Monotouch 中)

UITableView 索引路径行为表现奇怪

从横向旋转到纵向 (iPad) 后 UITableView 的奇怪行为

UITableView 奇怪的行为

UITableView + NSMutableArray 奇怪的行为

奇怪的行为 UIActionSheet + UITableView:行消失