UITableView dataSource 对象在滚动时变为空
Posted
技术标签:
【中文标题】UITableView dataSource 对象在滚动时变为空【英文标题】:UITableView dataSource objects become null when scroll 【发布时间】:2015-11-12 19:41:55 【问题描述】:我是CoreData
的新手,并使用MagicalRecord
来管理它。我的问题是我将UITableView
和NSArray
作为数据源填充了从CoreData
db 获取的对象,并且在我滚动表格一段时间之前一切似乎都很好。
这是我的代码:
获取数据的方法(MyDatabase.m):
+(NSArray *)getEntities
...
return [MyEntity MR_findAllSortedBy:@"name" ascending:YES withPredicate:predicate];
以下是我在 ViewController 中获取数据并将其设置为 UITableView
的方法:
- (void)viewDidLoad
[super viewDidLoad];
myEntitiesArray = [MyDatabase getEntities];
if(myEntitiesArray.count != 0)
[myTableView setTableData:myEntitiesArray];
这里是 MyTableView.m 中的setTableData
方法实现:
- (void)setTableData:(NSArray *)array
if (array && [array count] > 0)
_tableData = array;
[self reloadData];
下面是我在 MyTableView.m 中设置单元格的方式:
- (void)tableView:(UITableView *)tableView willDisplayCell:(SSCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
cell.nameLabel.text = [(MyEntity *)_tableData[indexPath.row] name];
我尝试将NSLog(@"name is %@",[(MyEntity *)_tableData[indexPath.row] name])
放入willDisplayCell
并发现当单元格为空时,NSLog
会打印出消息“名称为(空)”。在我遇到这个问题之前,我知道这个问题可能已经被很多人多次解决了。希望有人也能帮助我解决它:)
更新:cellForRowAtIndexPath
方法:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellIdentifier = @"ssCell";
SSCell *cell = (SSCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if( !cell )
[self registerNib:[UINib nibWithNibName:@"SSCell" bundle:nil] forCellReuseIdentifier:cellIdentifier];
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
[cell setSelectedBackgroundView:selectedBackgroundView];
cell.nameLabel.text = [(MyEntity *)_tableData[indexPath.row] name];
return cell;
我也在MyTableView.m
init方法里面调用了这个方法:
[self registerNib:[UINib nibWithNibName:@"SSCell" bundle:nil] forCellReuseIdentifier:@"ssCell"];
【问题讨论】:
你的 cellForRowAtIndexPath 方法在哪里?我认为当你必须使用 cellForRowAtIndexPath 时你正在使用 willDisplayCell @CCastro 看到我的更新,我将线路从willDisplayCell
移到 cellForRowAtIndexPath
并且没有运气
更改此单元格 = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];对于这个单元格 = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
我想知道以下哪个是 nil:tableData、tableData[indexPath.row]、名称甚至单元格。创建单元格的嵌套初始化是否可能失败?
使用 MR 而不是 FRC 应该会自动删除您的 SO 帐户。有多少问题涉及 MR 和由数组支持的 UITableView,这太疯狂了。只是说...
【参考方案1】:
您必须使用 cellForRowAtIndexPath。在这种方法中,单元被分配。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
/*
* This is an important bit, it asks the table view if it has any available cells
* already created which it is not using (if they are offscreen), so that it can
* reuse them (saving the time of alloc/init/load from xib a new cell ).
* The identifier is there to differentiate between different types of cells
* (you can display different types of cells in the same table view)
*/
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
/*
* If the cell is nil it means no cell was available for reuse and that we should
* create a new one.
*/
if (cell == nil)
/*
* Actually create a new cell (with an identifier so that it can be dequeued).
*/
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyIdentifier"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
/*
* Now that we have a cell we can configure it to display the data corresponding to
* this row/section
*/
cell.nameLabel.text = [(MyEntity *)_tableData[indexPath.row] name];
return cell;
【讨论】:
【参考方案2】:您应该通过调用 init.相反,您正在执行以下操作:
如果(!细胞) [self registerNib:[UINib nibWithNibName:@"SSCell" bundle:nil] forCellReuseIdentifier:cellIdentifier]; 单元格 = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath]; [单元格setSelectedBackgroundView:selectedBackgroundView];
当没有可用的单元格时,第二次调用尝试再次重用现有单元格。那可能会再次返回 nil。
要非常小心目标 C 的“特性”,调用 nil 对象的方法什么都不做。它不会像 Java 那样因 null.pointer.exception 而崩溃,它可能会漂浮在 [cell setSelectedBackgroundView:selectedBackgroundView] 和一大堆其他行上而没有问题。
【讨论】:
我知道UITableView
不会因为重复使用而为每一行创建UITableViewCell
。我创建了我的单元格并在cellForRowAtIndexPath
中重复使用它,单元格本身没有问题。我的数组中的对象有问题。附言试图将线路移动到cellForRowAtIndexPath
,但运气不好:(以上是关于UITableView dataSource 对象在滚动时变为空的主要内容,如果未能解决你的问题,请参考以下文章
UITableView 在 tableview.datasource 开始时崩溃
一行代码,快速为UITableView创建Delegate和DataSource
UITableView 仅用于 GUI 控件,没有 DataSource
UITableView dataSource 必须从 tableView:cellForRowAtIndexPath 返回一个单元格
在 ViewController 中使用带有外部 DataSource 和 UITableView 的自定义 UITableViewCell