下面这段代码乍一看没什么问题,其实会造成cell.buyBtnClick 捕获model的问题,造成点击按钮model不是正确model的bug
bug代码:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
QYMyCourseCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"QYMyCourseCell" forIndexPath:indexPath];
QYMyHomeCourseSubjectModel* subjectModel = [self.dataList safeObjectAtIndex:indexPath.section];
QYMyHomeCourseModel* model = [subjectModel.list safeObjectAtIndex:indexPath.item];
cell.model = model;
@weakify(self);
if (!cell.buyBtnClick) {
cell.buyBtnClick = ^{
@strongify(self);
NSString *name = model.title;
[[[UIAlertView alloc] initWithTitle:nil message:name delegate:nil cancelButtonTitle:@"0k" otherButtonTitles:nil, nil] show];
};
}
return cell;
}
来分析下这段代码:
由于block的实现是写在- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath,这个代理方法里面,
这个方法调用会很频繁,所以在cell的block的实现上加上 if (!cell.buyBtnClick) { .... } 的判断没有问题,可以避免block频繁创建的赋值,提升性能; 但是由于cell的复用机制,当列表中cell比较多时,cell循环利用,cell捕获的之前cell的model而不是当前的model.
正确的写法应该是,把model 作为cell的block的参数回调回来
@interface QYMyCourseCell : UICollectionViewCell
@property(nonatomic, strong) void (^buyBtnClick)(QYMyHomeCourseModel *model);
@end
@implementation DTMyCourseViewController
@weakify(self);
[self.buyBtn setBlockForControlEvents:UIControlEventTouchUpInside block:^(id _Nonnull sender) {
@strongify(self);
!self.buyBtnClick ? : self.buyBtnClick(self.model);
}];
@end
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
QYMyCourseCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"QYMyCourseCell" forIndexPath:indexPath];
QYMyHomeCourseSubjectModel* subjectModel = [self.dataList safeObjectAtIndex:indexPath.section];
QYMyHomeCourseModel* model = [subjectModel.list safeObjectAtIndex:indexPath.item];
cell.model = model;
@weakify(self);
if (!cell.buyBtnClick) {
cell.buyBtnClick = ^(QYMyHomeCourseModel * _Nonnull cellModel) {
@strongify(self);
NSString *name = cellModel.title;
[[[UIAlertView alloc] initWithTitle:nil message:name delegate:nil cancelButtonTitle:@"0k" otherButtonTitles:nil, nil] show];
};
}
return cell;
}
这样cell中的按钮点击时,回调回来的,永远是当前cell的model.
网友评论