美文网首页
记录一次cell的block捕获model引发的bug

记录一次cell的block捕获model引发的bug

作者: YannChee | 来源:发表于2020-03-09 18:03 被阅读0次

下面这段代码乍一看没什么问题,其实会造成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.

相关文章

  • 记录一次cell的block捕获model引发的bug

    下面这段代码乍一看没什么问题,其实会造成cell.buyBtnClick 捕获model的问题,造成点击按钮mod...

  • block:block捕获变量

    一、block捕获变量根儿上的东西 1、block会捕获局部变量 2、block不会捕获全局变量二、block捕获...

  • UITableViewCell嵌套UIScrollView

    直接上代码自定义Cell 控制器代码: 好了,效果如下: 注意一下cell重用引发的BUG。

  • block底层原理探究(二):内存管理

    前篇block底层原理探究(一):捕获,我们探究了block捕获外部变量的原理;如果block捕获的是对象类型的a...

  • 06.4-OC中block捕获对象类型的变量

    block捕获对象类型的变量 前面讲解的block变量捕获,我们讲解了block捕获基本数据类型的情况,下面我们再...

  • OC基础-Block(2)

    OC基础-Block(2)Block的变量捕获为了保证block内部能够正常访问外部的变量,block有个变量捕获...

  • Block变量捕获详解(一)

    什么是Block变量捕获block变量捕获就是在block内部创建一个变量来存放外部变量什么是值捕获block将外...

  • OC中的Block(二)

    block的变量捕获(capture) 为了保证block内部能够正常访问外部的变量,block有个变量捕获机制 ...

  • Block

    Block Block 可以捕获外部变量 Block 可以捕获来自外部作用域的变量,这是Block一个很强大的特性...

  • Block 第三次学习 感谢 MJ老师

    block 内部结构 Block block 变量捕获 变量类型捕获到block 内部访问方式局部变量auto(平...

网友评论

      本文标题:记录一次cell的block捕获model引发的bug

      本文链接:https://www.haomeiwen.com/subject/ghapdhtx.html