一.背景:接手了一个老项目, 领导让排查一个bug: 在私信详情页, 有一条发送失败的消息, 点击重发时,发送的消息不是当前点击的那一条.
二.查看代码:
cell中的代码
- (void)clickFailStatusImageView {
if (self.clickFailStatusImageViewBlock) {
self.clickFailStatusImageViewBlock(self);
}
}
cellForRow中的方法
cell.clickFailStatusImageViewBlock = ^(MessageDialogueCell * _Nonnull cell) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"重发该消息?" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *doneAction = [UIAlertAction actionWithTitle:@"重发" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSIndexPath *indexPath = [weakSelf.tableView indexPathForCell:cell];
MessageEntityMessage *message = weakSelf.dialogueMessages[indexPath.row];
[weakSelf sendMessage:message];
}];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:cancelAction];
[alert addAction:doneAction];
[weakSelf presentViewController:alert animated:YES completion:nil];
};
三.问题分析:
通过代码我们可以知道:在cell中, 按钮的点击事件是把cell的地址传出去, 在点击的回调中,点击后出现alert弹窗, 在弹窗的重发按钮点击事件中, 通过cell反查NSIndexPath.
为什么会出现取到的NSIndexPath不准的情况:
由于 UITableViewCell 是可重用的,如果点击cell上的重发按钮时, block保存了此cell的地址, 出现弹窗时, 在点击alert弹窗的重发按钮之前, 如果私信详情又有人发送了消息, 点击的cell被重用了, 此时再点击alert的重发按钮,通过 indexPathForCell: 方法返回的是当前可见的 cell 对应的 indexPath,不一定与被点击的按钮所在的 cell 的 indexPath 相同.所以会出现取到的NSIndexPath与点击的NSIndexPath不一致的情况.
四.解决方案:
在cell的按钮点击事件内部, 通过block向外传递模型数据, 外界直接使用模型数据完成重发逻辑, 无需再通过cell反查NSIndexPath和数据源通过NSIndexPath拿到具体的数据.
网友评论