您好我在我的应用上发现了一个问题,可能并不重要但很奇怪。
我在viewController中有一个开关,让我们称之为theSwitch,当我填充单元格时,在indexPath(0,0)上我将该开关作为附件视图。
单元格的标题会根据开关的状态而改变
//Code simplified for simplicity
if(indexPath.section == 0 && indexPath.row == 0) {
cell.textLabel.text = self.filtersActivatedSwitch.on ? NSLocalizedString(@"Filters activated", nil) : NSLocalizedString(@"Filters deactivated", nil);
cell.accessoryView = self.filtersActivatedSwitch;
}
按下开关时,此方法称为
-(void)switchActivated {
[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:VisibilityFilterTableViewSectionMasterFilter]];
}
这将创建一个死锁因为在方法cellForRowAtIndexPath上,当我尝试将单元格出列时,它将创建一个新的单元格(这经过测试,我认为它更有意义,它使用了我想要重新加载的相同单元格)在单元的配置中,开关将作为附件...添加...
这是一个棘手的地方......
BadPirate的答案解释了在tableviewcell上调用layoutSubview时的问题
When is layoutSubviews called?
-addSubview导致在添加的视图,要添加到的视图(目标视图)以及目标的所有子视图上调用layoutSubviews
我认为同样的事情应该发生在removeFromSupperview(假设)中,所以新的单元格中有layoutSubview被调用..它检查了accessoryView,看到它不是nil所以它添加它的ass子视图,另一方面在旧的单元格(由于任何原因没有出列,所以我无法清除accessoryView)layoutSubviews被调用因为removeFromSuperview(再次假设)它检查accessoryView不是nil,它将开关添加为子视图...并重复永远。
我的问题是......为什么表视图不会使用已经出列的单元格?两个tableviewcells具有相同的accessoryView的事实显然会使我的应用程序崩溃。
或者我认为附件视图错了?
干杯!
编辑: 这是prepareForReuse上的代码
- (void)prepareForReuse {
[super prepareForReuse];
for (UIView *view in self.contentView.subviews) {
[view removeFromSuperview];
}
for (UIView *view in self.imageView.subviews) {
[view removeFromSuperview];
}
self.textLabel.text = nil;
self.detailTextLabel.text = nil;
self.imageView.image = nil;
self.imageView.tag = 0;
self.accessoryView = nil;
}
答案 0 :(得分:3)
单元格被重复使用,因此可以在另一个位置重新使用从屏幕滚动的单元格,您仍然可以在其中添加任何子视图。在特定indexPath处添加附件视图时,您需要在其中包含“else”子句,以告知其他单元格没有该视图:我不知道你在cellForRowAtIndexPath:中做了什么,但在我的测试方法中,我根本不必使用prepareForReuse方法。我不确定我理解为什么在切换方法触发时会出现死锁,但是如果你在reloadRowsAtIndexPaths:withRowAnimation:方法中将动画设置为UITableViewRowAnimationNone,那么一切都有效。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
if(indexPath.section == 0 && indexPath.row == 0) {
cell.textLabel.text = self.filtersActivatedSwitch.on ? NSLocalizedString(@"Filters activated", nil) : NSLocalizedString(@"Filters deactivated", nil);
cell.accessoryView = self.filtersActivatedSwitch;
}else{
cell.textLabel.text = self.theData[indexPath.row];
cell.accessoryView = nil;
}
return cell;
}
-(void)switchActivated {
[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
}