美文网首页OC知识
OC 之 各种block 处理weakSelf

OC 之 各种block 处理weakSelf

作者: wustzhy | 来源:发表于2017-07-26 16:35 被阅读64次

    $ 问题抛出来

    1.所有自定义方法的block都需要__weak 吗?
    2.凡是, block内带 self的都需要 __weak 吗?
    3.凡是, 系统方法中的block, 都不需要__weak 吗?

      看看上述问题的反问语气, 相必语文过关的同学们都知道答案,一看就是 No No No ~         
      -> 😄 恭喜你~ right !
    

    $ but why ?

    至于原因 👇

    想必大伙都知道, 互相strong持有成了一个环 , 然后就无法释放了~


    $ block 常见场景(暂时想到的一些情况, 后续想到继续补充)

    first, code准备:
    👇 一个子View -- TestOneView, 创建各种参数为block的方法

     //  TestOneView.h
     #import <UIKit/UIKit.h>
    
     typedef void(^ZYOneBlock1)();
    
     typedef void(^ZYOneBlock2)();
    
     @interface TestOneView : UIView
     // copy修饰 
     @property (nonatomic,   copy)     ZYOneBlock1 oneBlock;
     // weak修饰
     @property (nonatomic,   weak)     ZYOneBlock1 weak_oneBlock;
     
     // 持有 传入的block , 但是 weak
     - (void)testWeakBlock:(ZYOneBlock1) block;
    
     // 不持有 传入的block , 在method中直接执行掉
     - (void)testBlock2WithBlock:(ZYOneBlock2) secondblock;
    
     @end
    
      // TestOneView.m
      #import "TestOneView.h"
    
      @implementation TestOneView
    
      /*
      // Only override drawRect: if you perform custom drawing.
      // An empty implementation adversely affects performance during animation.
      - (void)drawRect:(CGRect)rect {
          // Drawing code
      }
      */
    
      // 持有 传入的block , strong
      -(void)setOneBlock:(ZYOneBlock1)oneBlock{
          
          _oneBlock = oneBlock;
          _oneBlock();
      }
    
      // 持有 传入的block , 但是 weak
      - (void)testWeakBlock:(ZYOneBlock1) block;
      {
          self.weak_oneBlock = block;
      }
    
      // 不持有 传入的block , 在method中直接执行掉
      - (void)testBlock2WithBlock:(ZYOneBlock2) secondblock;
      {
          secondblock();
      }
      
      // 通过dealloc 检测能否释放
      -(void)dealloc{
          NSLog(@"%s",__func__);
      }
    
      @end
    

    go on ~ , code一个被push的VC -- TestOneViewController , 即是 block纵横所在的江湖

    😏😏😏 block 出场 😏😏😏


    • <1> A 操作 B的bloc

      (1).传给子View的block被子view 👉strong持有 , block块中使用了_ivar(成员变量) 、strong property , 处理方式如下:

        - (void)testStrongBlock_1{
            [self.view addSubview: self.oneView];
      
            __weak typeof(self) weakSelf = self;
            self.oneView.oneBlock = ^{
                __strong typeof(weakSelf) strongSelf = weakSelf;
                strongSelf->_intType = 11;
                strongSelf.pArray = @[@(11)];
            };
        }
      

      (2).传入的block块中 含有本类的实例方法

      - (void)testMethod_StrongBlock_1{
            
            [self.view addSubview: self.oneView];
            
            __weak typeof(self) weakSelf = self;
            self.oneView.oneBlock = ^{
                __strong typeof(weakSelf) strongSelf = weakSelf;
      
                // method
                [strongSelf containSelfMethod];
            };
        }
        - (void)containSelfMethod{
            _intType = 1010;
            self.pArray = @[@(2020)];
        }
      

      (3).传给子view的block 被子view 👉weak持有, 在方法内被执行完。 无需weakSelf

      - (void)testWeakBlock_1{
            
            [self.view addSubview: self.oneView];
            
            [self.oneView testWeakBlock:^{
                _intType = 111;
                self.pArray = @[@(1)];
            }];
        }
      

      (4).传给子view的block ❌不 被子view 持有, 直接执行掉。 无需weakSelf

        - (void)testParamBlock_2{
            
            [self.view addSubview: self.oneView];
            
            [self.oneView testBlock2WithBlock:^{
                _intType = 22;
                self.pArray = @[@(1)];
            }];
        }
      
    • <2> A 操作 A的block

      (a).block作参数, ❌不 被持有

        - (void)testParam_SelfBlock_1{
            [self testParam_SelfBlcokWith:^(NSArray * arr) {
                self.pArray = arr;
                NSLog(@"%s",__func__);
            }];
        }
        - (void)testParam_SelfBlcokWith:(MyBlockOne)myBlock{
            
            NSArray * arr = @[@"myblock1"];
            myBlock(arr);
            
        }
      

      (b).block作参数, 👉被持有

        - (void)testCopy_SelfBlock_1{
            
                __weak typeof(self) weakSelf = self;
            [self testCopy_SelfBlcokWith:^(NSArray * arr) {
                __strong typeof(weakSelf) strongSelf = weakSelf;
                
                strongSelf.pArray = arr;
                NSLog(@"%s",__func__);
            }];
        }
        - (void)testCopy_SelfBlcokWith:(MyBlockOne)myBlock{
            
            self.myBlock1 = myBlock;
            
            NSArray * arr = @[@"myblock1"];
            
            NSLog(@"%s",__func__);
            sleep(1);
            NSLog(@"%s",__func__);
            self.myBlock1(arr);
        }
      
    • <3> GCD的block(系统的) 无需weakSelf注意: GCD延时block, 会使VC pop后延迟释放
        - (void)didMoveToParentViewController:(UIViewController *)parent{
            
            [self.oneView removeFromSuperview];
            
            NSLog(@"%s , %@",__func__ ,self);
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                
                NSLog(@"%s , %@",__func__ ,self);
                [self testBackTimerAfter];  // 点击pop 时,会延迟2s dealloc
                
            });
        }
          - (void)testBackTimerAfter{
               
            [self.oneView testWeakBlock:^{
                NSLog(@"%s , %@",__func__ ,self);
            }];
            
            __weak typeof(self) weakSelf = self;
            _oneView.oneBlock = ^{
                __strong typeof(weakSelf) strongSelf = weakSelf;
                NSLog(@"%s , %@",__func__ ,strongSelf);
            };
        }
      
    • <4> ☺补充☺, 对于NSTimer addTarget: self...
      _weak typeof(self) weakSelf = self;
      _timer = [NSTimer scheduledTimerWithTimeInterval:3.0f
                                                target:weakSelf
                                              selector:@selector(timerFire:)
                                              userInfo:nil
                                               repeats:YES];
      

      对于如上解决方式, 是有误的,详解 可参考 👉 解决NSTimer/CADisplayLink的循环引用


    超懒人 点击 github demo 下载 调试 。
    祝愿有所收获哦 ~ _ ~

    相关文章

      网友评论

        本文标题:OC 之 各种block 处理weakSelf

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