UITableView 数据源方法的奇怪行为
Posted
技术标签:
【中文标题】UITableView 数据源方法的奇怪行为【英文标题】:Weird behavior of UITableView data source methods 【发布时间】:2013-12-06 18:12:21 【问题描述】:我想创建一个具有标准 tableview 数据源方法(-cellForRowAtIndexPath:
、-numberOfRows
等)的默认实现的 UIViewController
类。
我想创建一个自定义下拉列表。
这是我的问题的详细说明:
我定义了MyDropDownListController
类,它实现了UITableViewDelegate
和UITableViewDataSource
协议,其中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 中)
从横向旋转到纵向 (iPad) 后 UITableView 的奇怪行为