zoukankan      html  css  js  c++  java
  • iOS开发Block的介绍以及Block的循环引用问题

    1:block的循环引用问题最主要记住两点:

    如果【block内部】使用【外部声明的强引用】访问【对象A】, 那么【block内部】会自动产生一个【强引用】指向【对象A】

    如果【block内部】使用【外部声明的弱引用】访问【对象A】, 那么【block内部】会自动产生一个【弱引用】指向【对象A】

     2:

    #import "ViewController.h"
    #import "XMGPerson.h"
    
    @interface ViewController ()
    @property (nonatomic, copy) int (^sumBlock)(int, int);
    @property (nonatomic, assign) int a;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        
        [self test5];
        /*
         如果【block内部】使用【外部声明的强引用】访问【对象A】, 那么【block内部】会自动产生一个【强引用】指向【对象A】
         如果【block内部】使用【外部声明的弱引用】访问【对象A】, 那么【block内部】会自动产生一个【弱引用】指向【对象A】
         */
    }
    
    /**
     *  不可行
     */
    - (void)test6
    {
        XMGPerson *p = [[XMGPerson alloc] init];
        
        __weak XMGPerson *weakP = p;
        
        p.name = @"Jack";
        
        p.block = ^{ // block1
            XMGPerson *strongP = weakP;
            NSLog(@"block1 -- %@", strongP.name);
            
            dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
            dispatch_after(when, dispatch_get_main_queue(), ^{ // block2
                NSLog(@"block2 -- %@", weakP.name);
            });
        };
        
        p.block();
    }
    
    /**
     *  可行
     */
    - (void)test5
    {
        XMGPerson *p = [[XMGPerson alloc] init];
        
        __weak XMGPerson *weakP = p;
        
        p.name = @"Jack";
        
        p.block = ^{ // block1
            NSLog(@"beign-------");
            XMGPerson *strongP = weakP;
            
            dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
            dispatch_after(when, dispatch_get_main_queue(), ^{ // block2
                
                // NSLog(@"block2 -- %@", weakP.name);
                NSLog(@"block2 -- %@", strongP.name);
                
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // block3
                    NSLog(@"block3 -- %@", strongP.name);
                });
                
            });
        };
        
        p.block();
    }
    
    /**
     *  不可行
     */
    - (void)test4
    {
        XMGPerson *p = [[XMGPerson alloc] init];
        
        p.name = @"Jack";
        
        p.block = ^{ // block1
            NSLog(@"beign-------");
            
            dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
            dispatch_after(when, dispatch_get_main_queue(), ^{ // block2
                NSLog(@"after-----------%@", p.name);
            });
        };
        
        p.block();
    }
    
    /**
     *  不可行
     */
    - (void)test3
    {
        XMGPerson *p = [[XMGPerson alloc] init];
        __weak XMGPerson *weakP = p;
        
        p.name = @"Jack";
        
        p.block = ^{ // block1
            NSLog(@"beign-------");
            XMGPerson *strongP = weakP;
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(),
                           ^{ // block2
                               NSLog(@"after-----------%@", strongP.name);
                           });
        };
        
        p.block();
    }
    
    /**
     *  可行
     */
    - (void)test2
    {
        XMGPerson *p = [[XMGPerson alloc] init];
        
        __weak XMGPerson *weakP = p;
        
        p.name = @"Jack";
        p.block = ^{ // block1
            NSLog(@"beign-------");
            
            XMGPerson *strongP = weakP;
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(),
                           ^{ // block2
                               NSLog(@"after-----------%@", strongP.name);
                           });
        };
        
        p.block();
    }
    
    - (void)test1
    {
        XMGPerson *p = [[XMGPerson alloc] init];
        
        __weak XMGPerson *weakP = p;
        
        p.name = @"Jack";
        p.block = ^{
            NSLog(@"-----------%@", weakP.name);
        };
    }
    
    
    #pragma mark - 其他
    - (void)test:(int (^)(int, int))sumBlock
    {
        
    }
    
    - (void)run:(int)a
    {
        
    }
    
    - (void)testBlock
    {
        [self test:^(int a, int b){
            return a + b;
        }];
        
        
        void (^block)() =  ^{
            NSLog(@"-------");
        };
        block();
        
        
        
        
        int (^sumBlock)(int, int) = ^(int num1, int num2){
            return num1 + num2;
        };
        sumBlock(10, 10);
        
        
        int a = 10;
        
        /*
         返回值类型 (^block的变量名)(形参类型列表) = ^(形参列表) {
         // block代码
         };
         block的变量名(实参列表);
         */
    }
    
    @end

    总结:1:block的定义:1:block以属性定义的时候,用copy修饰,

    @property (nonatomic, copy) void (^block)();无参数无返回值,因为block默认是在堆里,需要将堆中的block,copy到栈中才能使用  2:block的非属性定义:1:无参数无返回值:

    其中 void (^block)() 表示声明一个名称为block的block,block的类型表示为:void (^)(),右边的为block任务的代码块,
        block();表示调用block,右边为左边的block赋值
      void (^block)() =  ^{
            NSLog(@"-------");
        };
        block();
     
    2:有参数有返回值的block:左边
    int (^sumBlock)(int, int)定义一个有参数有返回值的block:sumBlock,而右边的block给左边的block赋值,写法:参数写在^(int a,int b)其中ab为block的参数,返回值写在block的代码块中。
     sumBlock(10, 10);调用block,并未block传递参数
     ^(int num1, int num2){
            return num1 + num2;
        };
     
      int (^sumBlock)(int, int) = ^(int num1, int num2){
            return num1 + num2;
        };
        sumBlock(10, 10);
        
    3:block作为参数传递:1: block作为参数传递 - (void)test:(int (^)(int, int))sumBlock,实现该方法,调用block传递参数 2:在外部调用test方法,其中ab就为传递的参数,

         [self test:^(int a, int b){

            NSLog(@"%d",a+b);

            return a + b;

        }];

    - (void)test:(int (^)(int, int))sumBlock

    {   

    sumBlock(2,1);

    }

    4:1:block的循环引用:XMGPerson alloc init 之后在内存中产生一个对象,name 和 block是该对象的属性(因为用copy修饰,也就相当于强引用),则该对象会对这两个属性分别有一个强引用,创建完对象之后,有一个强指针p指向该对象(指针里存放的是对象的地址,变量创建之后无论是全局变量还是局部变量都会有一个强引用),__weak那部分代码是将强指针p的地址复制给一个弱指针weakSelf,此时弱指针weakSelf会有一个弱引用指向person对象,p.name = @"JACK";此时name属性会对jack有一个强引用,block会对赋值的block有一个强引用。此时不会立即调用block代码块中的任务,但是此时会检测block代码块中有无引用外部变量(即使是外部无引用,在after中引用了,也算block中引用了外部变量,此时会对访问的该对象有一个强引用或是弱引用,代码块中有引用weakP,所以会产生一个弱引用),再执行代码调用block,执行block代码块中的任务,将一个弱引用weakP指针赋值给一个强引用,此时block代码块中的strongP会对person对象有一个强引用,在执行gcd延迟函数,此时会产生延迟函数的block块,会检测延迟函数中有无引用外界的变量,有引用了strongP,则会产生一个强引用指向person对象,此时的代码块不立即执行(但是系统会有一个强指针指向该代码块,如图2),此时会执行到方法结束,强指针p销毁,弱指针weakp销毁,strongP执行完销毁,但此时block2还指向person对象,所以person对象不会销毁,能打印出name  2:像类似于GCD的延迟函数在block中,想要保住对象使其不备销毁,就在block中定义一个强引用指向就可以了

    
    
     







  • 相关阅读:
    js 模拟表单提交下载文件
    vue 刷新子组件方法解决使用v-if闪屏问题
    Java15-Tomcat&Servlet&HTTP&Request&Response
    JAVA26-SpringBoot-在线教育项目01
    20 Vue-ajax
    19 Vue-JQuery
    18 Vue-Json
    Java 20-Mybatis学习
    17 Vue-ES6语法之Promise、VueX、网络请求封装
    16 Vue-cli脚手架介绍与使用
  • 原文地址:https://www.cnblogs.com/cqb-learner/p/5797662.html
Copyright © 2011-2022 走看看