概念

  • block 是 C 语言的
  • 是一种数据类型,可以当作参数传递
  • 是一组预先准备好的代码,在需要的时候执行
  • 动画 block 回顾

    self.demoView.center = CGPointMake(self.view.center.x, );
    // 此方法会立即执行动画 block
    [UIView animateWithDuration:2.0 delay: usingSpringWithDamping:0.3 initialSpringVelocity: options: animations:^{
    NSLog(@"动画开始");
    self.demoView.center = self.view.center;
    } completion:^(BOOL finished) {
    // 会在动画结束后执行
    NSLog(@"动画完成");
    }];
    NSLog(@"come here");

    block 基本演练

    • 最简单的 block

      - (void)blockDemo1 {
      
          // 定义block
      // 类型 变量名 = 值
      void (^block)() = ^ {
      NSLog(@"Hello block");
      }; // 执行
      block();
      }

      使用 inlineBlock 可以快速定义 block,不过 block 一定要过关

    • 当作参数传递
      - (void)blockDemo2 {
      void (^block)() = ^ {
      NSLog(@"Hello block");
      }; [self demoBlock:block];
      } /// 演示 block 当作参数传递
      - (void)demoBlock:(void (^)())completion {
      NSLog(@"干点什么"); completion();
      }
    • 使用局部变量

      - (void)blockDemo3 {
      // 栈区变量
      int i = ;
      NSLog(@"%p", &i); void (^block)() = ^ {
      // 定义 block 的时候会对栈区变量进行一次 copy
      NSLog(@"Hello block %d %p", i, &i);
      }; [self demoBlock:block];
      }

      如果 block 中使用了外部变量,会对外部变量做一次 copy

    • 在 block 中修改外部变量
      - (void)blockDemo4 {
      // 栈区变量
      __block int i = ;
      NSLog(@"%p", &i); void (^block)() = ^ {
      // 定义 block 的时候会对栈区变量进行一次 copy
      NSLog(@"Hello block %d %p", i, &i);
      i = ;
      }; NSLog(@"block 定义完成 %p %d", &i, i); [self demoBlock:block]; NSLog(@"===>%d", i);
      }

      如果要在 block 内部修改栈区变量,需要使用 __block 修饰符,并且定义 block 之后,栈区变量的地址会变化为堆区地址block 的内存位置

      block 的内存位置

    • 全局区:如果block中没有使用任何全局变量
      • 栈区:如果 block 中使用了外部变量

        • MRC 模式可以看到
        • ARC 模式,系统会自动将 Block 复制到堆中
      • 堆区:将 block 设置给 copy 属性
        @property (nonatomic, copy) void (^myBlock)();
        - (void)blockDemo5 {
        int i = ;
        void (^block)() = ^ {
        NSLog(@"i --- %d", i);
        }; NSLog(@"%@", block); self.myBlock = block;
        } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"%@", self.myBlock);
        }

        注意:虽然目前 ARC 编译器在设置属性时,已经替程序员复制了 block,但是定义 block时,仍然建议使用 copy 属性

        // 面试题
        - (void)blockDemo4 {
        int i = ; // 提问:输出是几?
        // 10,定义 block 的时候,10已经被复制到堆中了
        void (^block)() = ^ {
        NSLog(@"%d", i);
        }; i = ; block();
        }

        问:block在哪里?=> 全局区

        - (void)blockDemo5 {
        // 问:block在哪里?=> 全局区
        // 原因:block 中没有使用任何的外部变量,不会因为任何外部因素而改变
        // 会保存在全局区
        void (^block)() = ^ {
        NSLog(@"hello world");
        };
        NSLog(@"%@", block);
        }

        问:block在哪里?=> 堆区

        - (void)blockDemo6 {
        int i = ;
        // 问:block在哪里?=> 堆区
        // 原因:因为用到了外部变量,而block准备好的代码,在`需要的时候`被执行
        // 调用方并不知道 block 什么时候会被调用
        // MRC 开发,block 在栈区,因为 MRC 的所有内存管理由程序员负责
        // ARC 开发,block 之所以在堆区,是因为编译器帮我们实现的
        // 问:为什么block属性要用 copy?
        void (^block)() = ^ {
        NSLog(@"hello %d", i);
        };
        NSLog(@"%@", block); // 在定义 block 属性的时候,必须使用 copy,这样在设置数值的时候,可以将栈区的 block 复制到堆中
        self.myBlock = block; NSLog(@"%@", self.myBlock);
        }
      • 总结:
      • Block 如果里边没有引用外边的任何变量,在全局区
      • Block 如果里边引用外边的任何变量,在堆区
      • MRC 的 Block 在栈区
      • ARC 的 Block 在堆区

block 的演练和使用的更多相关文章

  1. Block 及注意事项

    block 概念 block 是 C 语言的 是一种数据类型,可以当作参数传递 是一组预先准备好的代码,在需要的时候执行 block 的注意事项 (1)block 在实现时就会对它引用到的它所在方法中 ...

  2. 刀哥多线程笔记之gcd-02-block

    block 概念 block 是 C 语言的 是一种数据类型,可以当作参数传递 是一组预先准备好的代码,在需要的时候执行 动画 block 回顾 self.demoView.center = CGPo ...

  3. 05-UIKit绘图演练

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  4. 【精解】EOS智能合约演练

    EOS,智能合约,abi,wasm,cleos,eosiocpp,开发调试,钱包,账户,签名权限 热身 本文旨在针对EOS智能合约进行一个完整的实操演练,过程中深入熟悉掌握整个EOS智能合约的流程,过 ...

  5. Oracle RMAN 学习:演练进阶篇

    Oracle RMAN 学习:演练进阶篇 5 Rman备份演练进阶篇 5.1 是否选择增量备份 Backup命令生成的备份集中只备份了那些使用了的数据块,备份集实际大小已经较目标数据库的数据文件小了很 ...

  6. Flask基础(15)-->模板代码的复用【宏(Macro)、继承(Block)、包含(include)】

    宏 对宏(macro)的理解: 把它看作 Jinja2 中的一个函数,它会返回一个模板或者 HTML 字符串 为了避免反复地编写同样的模板代码,出现代码冗余,可以把他们写成函数以进行重用 需要在多处重 ...

  7. Html/CSS 示例演练 图书馆后台界面

    示例演练(html css javascript) --制作图书馆后台界面 1. 成品图

  8. css常用样式对文本的处理演练

    CSS文本属性可定义文本的外观,这是毫无疑问的,其次css可以通过以下属性改变文字的排版,比方说letter-spacing实现字符间距text-indent: 2em;完成首行缩进2字符word-s ...

  9. Kubernetes中分布式存储Rook-Ceph部署快速演练

    最近在项目中有涉及到Kubernetes的分布式存储部分的内容,也抽空多了解了一些.项目主要基于Rook-Ceph运行,考虑到Rook-Ceph部署也不那么简单,官方文档的步骤起点也不算低,因此,在整 ...

随机推荐

  1. 2016GIAC全球互联网架构大会日程分享

    GIAC全球互联网架构大会是中国互联网技术领域一年一度的行业盛事,每年从互联网架构最热门高压应对.云计算.大数据.机器学习.分布式架构等领域甄选前沿的有典型代表的技术创新及研发实践的架构案例,分享他们 ...

  2. block的内部实现原理

    一.简单定义 block是一个指向结构体的指针,编译器将block内部代码生成对应的函数,上述结构体中的函数指针(funcPtr)指向该函数的实现: 二.相关概念 形参和实参 形参:形式参数,用于定义 ...

  3. 从零开始学Axure原型设计(高级篇)

    如果你熟悉了Axure的部件库,那么你可以得心应手地画出心目中产品的线框图:如果你会用Axure的母版.动态面板功能,那么你应该能够画出一些简单网站的原型图:但只有你精通了Axure的条件逻辑.变量. ...

  4. Django中url匹配规则的补充

    Django中url匹配规则是在urls.py文件中配置的. 1.关于正则匹配优先级 在url匹配列表中,如果第一条和第二条同时满足匹配规则,则优先匹配第一条. 在url匹配列表中,如果第一条为正则模 ...

  5. shell 提取字符串

    记录一下: 我们可以用  ${ }  分别替换获得不同的值: file=/dir1/dir2/dir3/my.file.txt ${file#*/}:拿掉第一条  /  及其左边的字符串:dir1/d ...

  6. ECOS-Ecstore 后台管理地址修改

    ECStore默认出厂的后台管理地址是: http://域名/index.php/shopadmin http://域名/shopadmin [配置过rewrite后,并开启伪静态] 如果想要更个性的 ...

  7. linux服务器的操作禁忌

    1.linux系统是否支持开启SELINUX服务 我方linux系统的服务器不支持开启Selinux服务,如果开启了selinux服务,会导致系统异常并无法启动. 2.linux系统下能否开启NetW ...

  8. bootstrap validator html attributes 选项

    常用的html属性:data-fv-message="The username is not valid"data-fv-notempty="true"data ...

  9. iOS学习笔记(01) - 泛型

    决定新开一坑,在不断学习的同时分享自己的学习历程给大家,既是对自己学习的记录,又希望能对大家提供些微的帮助. 这一篇文章主要来介绍泛型的意义.使用与声明方法等. 1.泛型:限制类型 1.1.泛型使用场 ...

  10. stm32菜单按键的设计

    有点懒.看注释吧 // k0,enter/enable;k3:esc/disable// k1,value+/menu+;k2:menu-/value-; #include "sysmenu ...