[每天记录一个Bug]Cell中由于block加载网络请求产生的复用
2017-12-15 12:45
671 查看
Bug 出现场景:
cell中使用加载图片的网络请求出现复用,截图如下:
复用原因:
Cell Model中只有一个用户的uid,所有用户相关信息:例如头像\名称\信息等是通过 block请求,通过uid 回调中取到的字段,但由于是在cell中通过系统的block回调中下载得到的头像,所以会有延时问题.
当使用 self.collection reloadData ,这个语句的时候,由于4个cell的头像还没加载成功,瞬间又重新复用4个cell出来,就会产生复用的情况。
也就是说 4个cell地址如下:
0XA1
0XA2
0XA3
0XA4
4个cell地址正序排列,分别取block请求拉取头像的时候,此时还没有拉取成功,瞬间执行语句 self.collection reloadData。cell 会产生复用机制,地址排列顺序如下:
0XA4
0XA3
0XA2
0XA1
此时就会产生复用,由于第一个cell网络请求较快,但是第4个cell请求比较慢,就会产生复用:
因为
0XA1 头像加载成功
0XA2
0XA3
0XA4 头像未加载成功
reloadData后复用
0XA4 头像加载成功,但是由于复用之前block还没有加载成功,导致在之前cell中的0XA4的头像直接覆盖了,复用后的0XA4的头像。
0XA3
0XA2
0XA1 由于复用钱0XA1头像加载速度较快,所以这个cell不会出现复用情况。适合网络加载快慢相关
cell中使用block进行网络请求,就容易出现此问题。
即时在 cell中的 prepareReuse()方法中将cell置nil,也会出现复用问题,因为根本原因是在block块中出现的复用问题。
解决方案:
在 block 块中 ,记录回调前的 user.uid 数据,然后和 cell此时记录的变量 model.uid 进行对比,因为model.uid是cell自带的字段,不会被复用的字段,而block中的user.uid是block回调后的字段,可能是之前cell中保留的字段。
进行对比,就知道block是复用前的,还是复用后的。
block里的变量不会变,但是复用后的cell Model会变。
解决方案 :
user.uid block回调产生的用户字段,_chatModel.chatCreater 是Model中的字段,不会被block所截取的临时变量。
if ([_chatModel.chatCreaterisEqualToString:user.uid]) {
//没被复用
}
else {
//被复用
}
代码如下:
IDSLOG(@"Home msg. model.chatCreater: %@,cell:%@", model.chatCreater,self);
@weakify(self);
[[IDSUserCachesharedCache] findUser:model.chatCreatercallback:^(NSArray<IDSLoginUser *> *users) {
@strongify(self);
if (IS_NS_COLLECTION_EMPTY(users)) {
return;
}
IDSLoginUser *user = [users cl_objectAtIndex:0];
IDSLOG(@"_chatModel.chatCreater : %@, user.uid:%@, model.chatCreater:%@", _chatModel.chatCreater, user.uid, model.chatCreater);
if ([_chatModel.chatCreaterisEqualToString:user.uid]) {
NSURL *bgimageUrl = nil;
if (!IS_NS_STRING_EMPTY(user.avatar_url)){
bgimageUrl = [AppUtilurlEncodeToNSURL:user.avatar_url];
}
staticUIImage *defImg;
staticdispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
defImg = [[IDSImageManagersharedManager] defaultAvatar:CircleStyle];
});
[self.avatarImageViewsd_setImageWithURL:bgimageUrl
placeholderImage:defImg
options:SDWebImageRetryFailed|SDWebImageLowPriority];
self.nameLabel.text = user.username;
self.nameLabel.frame = CGRectMake(CGRectGetMaxX(self.avatarImageView.frame)+7,
CGRectGetMinY(self.chatLabel.frame)-7-self.nameLabel.contentSize.height, 0, 0);
self.avatarImageView.layer.cornerRadius = self.avatarImageView.frame.size.width/2.0;
[self.nameLabelsizeToFit];
self.timeLabel.frame = CGRectMake(CGRectGetMaxX(self.nameLabel.frame)+5, 0, 0, 0);
self.timeLabel.text = [TimeUtilcl_prettyDateWithReference:_chatModel.timestamp];
[self.timeLabelsizeToFit];
self.timeLabel.centerY = self.nameLabel.centerY;
}
}];
cell中使用加载图片的网络请求出现复用,截图如下:
复用原因:
Cell Model中只有一个用户的uid,所有用户相关信息:例如头像\名称\信息等是通过 block请求,通过uid 回调中取到的字段,但由于是在cell中通过系统的block回调中下载得到的头像,所以会有延时问题.
当使用 self.collection reloadData ,这个语句的时候,由于4个cell的头像还没加载成功,瞬间又重新复用4个cell出来,就会产生复用的情况。
也就是说 4个cell地址如下:
0XA1
0XA2
0XA3
0XA4
4个cell地址正序排列,分别取block请求拉取头像的时候,此时还没有拉取成功,瞬间执行语句 self.collection reloadData。cell 会产生复用机制,地址排列顺序如下:
0XA4
0XA3
0XA2
0XA1
此时就会产生复用,由于第一个cell网络请求较快,但是第4个cell请求比较慢,就会产生复用:
因为
0XA1 头像加载成功
0XA2
0XA3
0XA4 头像未加载成功
reloadData后复用
0XA4 头像加载成功,但是由于复用之前block还没有加载成功,导致在之前cell中的0XA4的头像直接覆盖了,复用后的0XA4的头像。
0XA3
0XA2
0XA1 由于复用钱0XA1头像加载速度较快,所以这个cell不会出现复用情况。适合网络加载快慢相关
cell中使用block进行网络请求,就容易出现此问题。
即时在 cell中的 prepareReuse()方法中将cell置nil,也会出现复用问题,因为根本原因是在block块中出现的复用问题。
解决方案:
在 block 块中 ,记录回调前的 user.uid 数据,然后和 cell此时记录的变量 model.uid 进行对比,因为model.uid是cell自带的字段,不会被复用的字段,而block中的user.uid是block回调后的字段,可能是之前cell中保留的字段。
进行对比,就知道block是复用前的,还是复用后的。
block里的变量不会变,但是复用后的cell Model会变。
解决方案 :
user.uid block回调产生的用户字段,_chatModel.chatCreater 是Model中的字段,不会被block所截取的临时变量。
if ([_chatModel.chatCreaterisEqualToString:user.uid]) {
//没被复用
}
else {
//被复用
}
代码如下:
IDSLOG(@"Home msg. model.chatCreater: %@,cell:%@", model.chatCreater,self);
@weakify(self);
[[IDSUserCachesharedCache] findUser:model.chatCreatercallback:^(NSArray<IDSLoginUser *> *users) {
@strongify(self);
if (IS_NS_COLLECTION_EMPTY(users)) {
return;
}
IDSLoginUser *user = [users cl_objectAtIndex:0];
IDSLOG(@"_chatModel.chatCreater : %@, user.uid:%@, model.chatCreater:%@", _chatModel.chatCreater, user.uid, model.chatCreater);
if ([_chatModel.chatCreaterisEqualToString:user.uid]) {
NSURL *bgimageUrl = nil;
if (!IS_NS_STRING_EMPTY(user.avatar_url)){
bgimageUrl = [AppUtilurlEncodeToNSURL:user.avatar_url];
}
staticUIImage *defImg;
staticdispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
defImg = [[IDSImageManagersharedManager] defaultAvatar:CircleStyle];
});
[self.avatarImageViewsd_setImageWithURL:bgimageUrl
placeholderImage:defImg
options:SDWebImageRetryFailed|SDWebImageLowPriority];
self.nameLabel.text = user.username;
self.nameLabel.frame = CGRectMake(CGRectGetMaxX(self.avatarImageView.frame)+7,
CGRectGetMinY(self.chatLabel.frame)-7-self.nameLabel.contentSize.height, 0, 0);
self.avatarImageView.layer.cornerRadius = self.avatarImageView.frame.size.width/2.0;
[self.nameLabelsizeToFit];
self.timeLabel.frame = CGRectMake(CGRectGetMaxX(self.nameLabel.frame)+5, 0, 0, 0);
self.timeLabel.text = [TimeUtilcl_prettyDateWithReference:_chatModel.timestamp];
[self.timeLabelsizeToFit];
self.timeLabel.centerY = self.nameLabel.centerY;
}
}];
相关文章推荐
- 网络连接复用不得回避的一个关键问题:谁先发起请求:
- 记录一个cell的Action事件无响应bug
- block传值以及利用block封装一个网络请求类
- 《android网络请求框架》一个轻量级的异步网络请求框架MyHttpUtils(新版更新记录,版本号:2.X)
- 渣渣用JavaScript开发的消消乐,由于没有按照正规消消乐形式生成,是随机产生图形,所以存在一个算法bug,具体看下面,高手想到可以告诉我
- (一个常用的案例)Fragment xlistview pull 网络请求 刷新分页加载 ImageLoader
- 把网络请求加载过程dialog做成一个View
- 关于网络请求的一个异常bug(java.lang.IllegalArgumentException: Host name may not be null)
- 把网络请求加载过程dialog做成一个View
- [Socket网络编程]由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。
- iOS tableViewCell 在cell赋值、网络加载照片位置偏移大小错乱,做一个类似qq列表的tableview 更新3
- html自动请求加载两次(html中一个无比奇葩的bug)
- 点击侧滑任何一个 菜单项,请求网络数据展示在主界面的xlistview中且实现下拉刷新效果和上拉加载的分页加载数据效果
- Android 学习记录-网络请求
- 程序在4441端口监听,当检测到有客户机请求时,产生一个内为“客户,你好,我是服务器”的字符串输出到客户端
- 一个由于spring事务引起的bug
- IOS网络第二天 - 02-异步HTTP请求block回调 解析
- 用dwz时, 由于粗心产生的一些问题(记录方便自己查阅)
- 一个异步网络请求的坑:关于NSURLConnection和NSRunLoopCommonModes