• block



    不使用__block修饰:
    int num = 1;
        self.myBlock = ^(){
           NSLog(@"block num == %d",num);
        };
        
        num = 2;
        self.myBlock();
        NSLog(@"last num == %d",num);
    
    // 输入结果:
    // 2016-09-13 13:13:15.362 block2[7543:562614] block num == 1
    // 2016-09-13 13:13:15.363 block2[7543:562614] last num == 2
    num 使用__block修饰后:

    __block int num = 1; self.myBlock = ^(){ NSLog(@"block num == %d",num); }; num = 2; self.myBlock(); NSLog(@"last num == %d",num); // 输出结果: // 2016-09-13 13:14:20.964 block2[7574:570584] block num == 2 // 2016-09-13 13:14:20.964 block2[7574:570584] last num == 2

    如果不用__block修饰变量,在block内强行修改变量会报错:

    增加__block后,可以在block内部修改num:

    __block int num = 1;
        self.myBlock = ^(){
            num = 3;
           NSLog(@"block num == %d",num);
        };
        
        num = 2;
        self.myBlock();
        NSLog(@"last num == %d",num);
    
    // 输出结果:
    // 2016-09-13 13:16:44.961 block2[7632:585368] block num == 3
    // 2016-09-13 13:16:44.962 block2[7632:585368] last num == 3

    block调用完后再修改num:

        __block int num = 1;
        self.myBlock = ^(){
            num = 3;
           NSLog(@"block num == %d",num);
        };
        
        self.myBlock();
        num = 2;
        NSLog(@"last num == %d",num);
    // 输出结果:
    // 2016-09-13 13:18:38.332 block2[7681:599563] block num == 3
    // 2016-09-13 13:18:38.333 block2[7681:599563] last num == 2

    block对对象类型的使用和对基本数据类型的使用一样:

    不用__block修饰:

        NSString *str = @"1";
        self.myBlock = ^(){
            NSLog(@"block str == %@",str);
        };
        str = @"2";
        self.myBlock();
        NSLog(@"last str == %@",str);
    
    // 输出结果:
    // 2016-09-13 13:23:03.091 block2[7815:628689] block str == 1
    // 2016-09-13 13:23:03.092 block2[7815:628689] last str == 2

    使用__block修饰:

        __block NSString *str = @"1";
        self.myBlock = ^(){
            NSLog(@"block str == %@",str);
        };
        str = @"2";
        self.myBlock();
        NSLog(@"last str == %@",str);
    
    // 输出结果:
    // 2016-09-13 13:25:17.199 block2[7867:638529] block str == 2
    // 2016-09-13 13:25:17.199 block2[7867:638529] last str == 2

    block内部修改对象:

        __block NSString *str = @"1";
        self.myBlock = ^(){
            str = @"3";
            NSLog(@"block str == %@",str);
        };
        str = @"2";
        self.myBlock();
        NSLog(@"last str == %@",str);
    
    // 输出结果:
    // 2016-09-13 13:27:49.440 block2[7937:651966] block str == 3
    // 2016-09-13 13:27:49.441 block2[7937:651966] last str == 3

    block调用完后再修改对象:

        __block NSString *str = @"1";
        self.myBlock = ^(){
            str = @"3";
            NSLog(@"block str == %@",str);
        };
        self.myBlock();
        str = @"2";
        NSLog(@"last str == %@",str);
    
    // 输出结果:
    // 2016-09-13 13:29:03.705 block2[7973:660957] block str == 3
    // 2016-09-13 13:29:03.705 block2[7973:660957] last str == 2

    总结:

    __block的使用:

    block对基本数据类型和对象类型的使用注意是一样的。即:

      无论是基本数据类型还是对象类型,如果想在block内部改变外面变量的值,必须用__block修饰;如果外面的值改变也要影响block内部值,也必须用__block修饰。(与block外面的变量的值保持同步)
      即如果想内部改变影响外部或者外部改变影响内部,那么变量必须用__block修饰
      如果不加__block修饰,那么block会捕获变量的值,在之后不受外面变量的改变而改变;并且也不能在block内部修改变量的值
      如果想在block内部修改变量的值,必须用__block修饰

    block循环引用:

    伴随着block能够捕获变量的能力的一个问题就是, 循环引用, 在ARC中, 只要不是用到纯C语言的库,管理内存的工作都不需要我们完成, 但是循环引用却是我们需要解决的, 最常见的就是当block捕获的变量是一个对象的属性(方法)的时候, 也就是会捕获到self, 那么这个时候就可能会造成循环引用(block属性应该被标记为copy), 解决方法也很简单, 使用一个对self弱引用的指针即可, 这个写法就很多了, 笔者习惯的写法是: __weak typeof(self) weakSelf = self;, 那么在block中使用weakSelf替代self调用相关的属性或者方法, 就不会造成循环引用

    weakSelf和strongSelf:

    使用weakSelf能够解决block捕获self造成的循环引用的内存泄漏问题, 但是带来的另一个问题就是, 特别是在多线程中,可能在block中代码正在执行的时候, self被销毁了, 因为使用weakSelf捕获到的是self的弱引用, 那么后续的代码就不能够继续执行了, 这个时候为了保证在这个block中self即使被销毁block里面的代码也能正常执行, 我们需要的另一个操作就是, 将weakSelf强引用一次, 让他的引用计数加1, 就能处理这个问题, 就是Apple在wwdc中提到的weak-strong-dance, 笔者习惯的书写方式是: __strong typeof(self) strongSelf = weakSelf;,,, 当然这个必须要明白的是, 这个block里面的strongSelf能够保证里面代码执行完毕的前提是程序能够执行到block, 如果在执行block之前self已经被销毁了, 那么这个block肯定是不会被调用的(block的引用计数已经为0).

  • 相关阅读:
    微软校园招聘  研发工程师A
    版本号排序
    腾讯2018校园招聘  研发工程师笔试题(三)
    好词好句
    HikariCP 连接最快的连接池
    Ubuntu 18.04.1 安装java8
    Ubuntu 18.04.1 安装mysql 5.7.27
    markdown 插入链接
    面试题 int(3) int(10) 区别
    采购单(京东2017秋招真题)
  • 原文地址:https://www.cnblogs.com/wsnb/p/5868169.html
Copyright © 2020-2023  润新知