多次加载时 cellForRowAtIndexPath 行为异常
Posted
技术标签:
【中文标题】多次加载时 cellForRowAtIndexPath 行为异常【英文标题】:cellForRowAtIndexPath misbehaves when loading more than once 【发布时间】:2014-11-28 14:24:54 【问题描述】:我使用以下代码创建了一个带有滑动手势的应用程序。手势应仅适用于特定行。第一次加载时它工作得很好。从第二次开始,手势功能对每一行都有效。
我的代码如下:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
GoalDetailsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"GoalDetailsCell"];
if(cell == nil)
cell = [[GoalDetailsTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"GoalDetailsCell"];
NSMutableDictionary *cellData = [self.databaseCall transactionFromDatabase:indexPath.row goalId:self.goalId andStageId:self.stageId];
cell.goalDescription.text = self.goalName;
cell.actionGoalDescription.text = self.goalName;
cell.tipsDescription.text = [cellData objectForKey:@"tipsDescription"];
UIImage *cellImage = [UIImage imageNamed:[cellData objectForKey:@"categoryImage"]];
NSLog(@"%@", [cellData objectForKey:@"cardType"]);
if([[cellData objectForKey:@"cardType"] isEqualToString:@"2"])
UISwipeGestureRecognizer *swipeLeftGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeftMethod:)];
swipeLeftGesture.direction = UISwipeGestureRecognizerDirectionLeft;
[cell.cardDetails addGestureRecognizer:swipeLeftGesture];
[cell.tryThisButton addTarget:self action:@selector(tryThisButtonPressed:) forControlEvents:UIControlEventTouchDown];
UISwipeGestureRecognizer *swipeRightGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRightMethod:)];
swipeRightGesture.direction = UISwipeGestureRecognizerDirectionRight;
[cell.actionCardReminder addGestureRecognizer:swipeRightGesture];
[cell.previousButton addTarget:self action:@selector(previousButtonPressed:) forControlEvents:UIControlEventTouchDown];
cell.tryThisButton.hidden = NO;
[cell.tryThisButton setImage:[UIImage imageNamed:@"trythis.jpg"] forState:UIControlStateNormal];
[cell.actionCardType setImage:[UIImage imageNamed:@"toconsider.jpg"]];
cell.cardType.image = [UIImage imageNamed:@"toconsider.jpg"];
cell.cardTypeImage.hidden = YES;
cell.actionCardGoalName.text = self.goalName;
cell.actionGoalsImage.image = cellImage;
cell.actionCardReminder.layer.cornerRadius = 5;
cell.datePicker.layer.borderWidth = 0.2;
cell.datePicker.layer.borderColor = [[UIColor grayColor] CGColor];
else
cell.tryThisButton.hidden = YES;
cell.cardTypeImage.hidden = NO;
cell.cardType.image = [UIImage imageNamed:@"goodtoknow.jpg"];
cell.cardTypeImage.image = [UIImage imageNamed:@"tips.jpg"];
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:[cellData objectForKey:@"actionLink"]];
[str addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:NSMakeRange(0, [str length])];
[str addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSUnderlineStyleSingle] range:NSMakeRange(0, [str length])];
[cell.reminderSwitch addTarget:self action:@selector(customSwitchChanged:) forControlEvents:UIControlEventValueChanged];
[cell.datePicker addTarget:self action:@selector(datePickerButtonPressed:) forControlEvents:UIControlEventTouchDown];
cell.weburl.attributedText = str;
cell.goalName.text = self.goalName;
cell.goalsImage.image = cellImage;
cell.cardDetails.layer.cornerRadius = 5;
NSLog(@"%d", indexPath.row);
// Configure the cell...
return cell;
提前致谢。
【问题讨论】:
尝试为每种细胞类型使用两个不同的类。 你能给我一些示例程序吗 我放了一些代码作为答案(因为太长了,不能作为评论发表)。 【参考方案1】:这是因为您使用 dequeueReusableCellWithIdentifier:
重复使用您的单元格以进行快速修复,您也许可以在 else 语句中明确删除手势识别器,例如:
else
cell.tryThisButton.hidden = YES;
cell.cardTypeImage.hidden = NO;
cell.cardType.image = [UIImage imageNamed:@"goodtoknow.jpg"];
cell.cardTypeImage.image = [UIImage imageNamed:@"tips.jpg"];
// To remove all swipe gestures:
for (UIGestureRecognizer *recognizer in cell.cardDetails.gestureRecognizers)
[cell.cardDetails removeGestureRecognizer:recognizer];
for (UIGestureRecognizer *recognizer in cell.actionCardReminder.gestureRecognizers)
[cell.actionCardReminder removeGestureRecognizer:recognizer];
不过,我确实认为有更好的方法来构建您的代码,因为当您重用单元格时,您实际上也是在将手势识别器一层一层地分层。我认为您需要想办法重用手势识别器,就像重用其他插座一样。但是为了快速解决问题,我的解决方案应该可以工作。
【讨论】:
它显示以下错误 -[UIView countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x7aff2f60 @Balaji 对此感到抱歉。我在循环行的末尾省略了“.gestureRecognizers”。现在应该可以工作了。 @Balaji cardDetails 和 actionCardReminder 是什么? UIViews? @Balaji 实际拍摄。我又犯了一个错误。马上更新。 cardDetails 和 actionCardDetails 是表格单元格中的 uiViews。实际上错误已经消失,但行为与问题中的相同。【参考方案2】:您已经标记了答案,但这里还有一些代码:
在你看来DidLoad:
[self.tableView registerClass:[GoalDetailsTableViewCell class] forCellWithReuseIdentifier:@"GoalDetailsCell"];
[self.tableView registerClass:[GoalDetailsTableViewCellWithGestures class] forCellWithReuseIdentifier:@"GoalDetailsCellWithGestures”];
在你的 cellForRowAtIndexPath 中:
if([[cellData objectForKey:@"cardType"] isEqualToString:@"2"])
GoalDetailsTableViewCellWithGestures *cell = [tableView dequeueReusableCellWithIdentifier:@"GoalDetailsCellWithGestures"];
// configure this type of cell (text, gestures, etc)
return cell;
else
GoalDetailsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"GoalDetailsTableViewCell"];
// configure this type of cell (text, etc)
return cell;
【讨论】:
但我没有任何标识符为“GoalDetailsCellWithGestures”的单元格 这就是想法:创建两种不同类型的单元格(一种有手势,另一种没有手势)并相应地配置它们。以上是关于多次加载时 cellForRowAtIndexPath 行为异常的主要内容,如果未能解决你的问题,请参考以下文章
多次加载时 cellForRowAtIndexPath 行为异常
重新加载 Fragment 时多次调用 Fragment onCreate