block(代码块)

1.1 什么是block

  • block是iOS中一种比较特殊的数据类型。(可以定义变量、做形参或返回值)
  • block是苹果官方特别推荐使用的数据类型,应用场景比较广泛
  • 动画
  • 多线程
  • 集合遍历
  • 网络请求回调

      在多线程和网络也使用得相当频繁,一般都是作为回调使用!

  • block的作用
  • 和函数一样,用来保存某一段代码,可以在恰当的时间再取出来调用
  • block功能类似于函数(方法),比函数更强大。
  • block是一种数据类型,可以嵌套定义,随时调用。

Xcode输入 inline 可快速生成(快捷键)

1.2 block的格式    

  

block ios 点语法 ios中block_block ios 点语法

  • 比较函数、函数指针、block:

     

block ios 点语法 ios中block_block ios 点语法_02

  

block没有参数, 那么^后面的()可以省略

  • block案例

block ios 点语法 ios中block_block ios 点语法_03

1.3 给block类型取别名(类比函数指针)

     

block ios 点语法 ios中block_xcode_04

变量的名称就是类型名称(即别名)

     

block ios 点语法 ios中block_局部变量_05

1.4 block的应用场景

   当前面代码块一样,后面代码块一样,中间的代码块不一样,中间的代码块就用block。

    

block ios 点语法 ios中block_block ios 点语法_06

1.5 block的注意事项

  • block中可以定义和外界同名的变量,但是在block中访问的是block中定义的变量(就近原则,和函数一样)

     

block ios 点语法 ios中block_代码块_07

  • 在代码块中可以访问外面的变量

    (1)在代码块中可以直接访问和修改非栈区的变量(使用的是同一个变量)

 

      

block ios 点语法 ios中block_局部变量_08

    (2)栈区的变量可以访问,但默认不能修改(使用的是不同的变量,实际上访问的是自己拷贝的值)

block中的变量和外界的局部变量并不是同一个变量,block会将外界的变量拷贝一份到堆内存中

中使用的外界变量是copy的,所以在调用之前修改外界变量的值,不会影响到block中copy的值

      

block ios 点语法 ios中block_block ios 点语法_09

在代码块中修改局部变量编译不通过。怎么在代码块中修改局部变量呢?在局部变量前面加上关键字:__block

         

block ios 点语法 ios中block_block ios 点语法_10

  

block ios 点语法 ios中block_局部变量_11

1.6 面试题:block是存储在堆中还是栈中?

  • 默认情况下block存储在栈中,如果对block进行一个copy操作,block会转移到堆中
  • 如果block在栈中, block中访问了外界的对象, 那么不会对对象进行retain操作
  • 如果block在堆中, block中访问了外界的对象, 那么会对外界的对象进行一次retain

    

block ios 点语法 ios中block_局部变量_12

1.7 block的内存泄露体现

block在copy时都会对block内部用到的对象进行强引用(ARC)或者retainCount增1(非ARC)。

在ARC与非ARC环境下对block使用不当都会引起循环引用问题。

一般表现为:

  某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是

     

block ios 点语法 ios中block_局部变量_13

    

block ios 点语法 ios中block_局部变量_14

1)MRC情况下,用__block可以消除循环引用。

2)ARC情况下,必须用弱引用才可以解决循环引用问题,iOS5之后可以直接使用__weak,之前则只能使用__unsafe_unretained了,__unsafe_unretained缺点是指针释放后自己不会置空。

 

什么时候栈上的Block会复制到堆呢?

  • 调用Block的copy实例方法时
  • Block作为函数返回值返回时
  • 将Block赋值给附有__strong修饰符、id类型的类或Block类型成员变量时
  • 在方法名中含有usingBlock的Cocoa框架方法或GCD的API中传递Block时

     

    block很多的用处是跨越两个类来使用的。

实现两个页面之间的传值:

  • 通过“协议/代理”实现两个页面之间传值
  • 使用block作为property,实现两个页面之间传值

 

面试题:

    

block ios 点语法 ios中block_局部变量_15