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
.
chatCreater
isEqualToString
:user.
uid
]) {
//没被复用
}
else {
//被复用
}
代码如下:
IDSLOG
(
@"Home msg. model.chatCreater: %@,cell:%@"
, model.
chatCreater
,
self
);
@
weakify
(
self
);
[[
IDSUserCache
sharedCache
]
findUser
:model.
chatCreater
callback
:^(
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
.
chatCreater
isEqualToString
:user.
uid
]) {
NSURL
*bgimageUrl =
nil
;
if
(!
IS_NS_STRING_EMPTY
(user.
avatar_url
)){
bgimageUrl = [
AppUtil
urlEncodeToNSURL
:user.
avatar_url
];
}
static
UIImage
*defImg;
static
dispatch_once_t
onceToken;
dispatch_once
(&onceToken, ^{
defImg = [[
IDSImageManager
sharedManager
]
defaultAvatar
:
CircleStyle
];
});
[
self
.
avatarImageView
sd_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
.
nameLabel
sizeToFit
];
self
.
timeLabel
.
frame
=
CGRectMake
(
CGRectGetMaxX
(
self
.
nameLabel
.
frame
)+
5
,
0
,
0
,
0
);
self
.
timeLabel
.
text
= [
TimeUtil
cl_prettyDateWithReference
:
_chatModel
.
timestamp
];
[
self
.
timeLabel
sizeToFit
];
self
.
timeLabel
.
centerY
=
self
.
nameLabel
.
centerY
;
}
}];