iOS中的Block

Block
使用^来声明一个block变量

void (^printBlock)(NSString *x); printBlock =^(NSString *str){ NSLog(@"print:%@",str); };

【iOS中的Block】返回值 ^block名 形参 {块内容}
概述
  • 在很多情况下,并不需要将block声明一个变量,在需要使用block的地方直接用内嵌的方式将block的内容写出来
  • 一般来说block只能读取在同一个作用于的变量而没有办法修改在block外定义的任何变量,此时若我们想这些变量能在block中被修改,就必须使用__block修饰词。如下,有修饰词的变量可写,没有__block修饰的变量只读
    • __block不能修饰长度为不定值的变量
__block int NBNum = 1; int notNBNum = 0; void (^doSomeThing)(int n); doSomeThing = ^(int n){ NBNum++; NSLog(@"%d",NBNum); NSLog(@"%d",notNBNum) };

功能 Block是一种具有匿名功能的内嵌函数,
  • 它的特性如下:
    1. 形参
    2. 有返回值
    3. lexical scope(作用域)
  • 它的使用时机:表示,简化一段代码,特别适合用于封装一些小型的task或者作为一个工作完成的callback
  • 它的优点(相对于delegatecallback):
    1. 可以直接在block中直接写入等下要执行的代码,直接将代码变成函数的参数传入函数中,这是block最常使用的地方
    2. 可以存储局部变量,传统的callback读写局部变量需要把数据封装成一个结构体,而block可以直接存取
  • 引用计数
    • 如果在blcok中引用了OC对象,那么引用计数+1;__block对引用计数无影响
  • 使用注意
    • 避免在if for循环等局部定义域内定义block并在其外面引用
Block的本质 当你定义完block之后,其实是创建了一个函数,在创建结构体的时候把函数的指针一起传给了block,所以之后可以拿出来调用
__block修饰的变量传入Blcok是地址传递,普通变量传入block是值传递
Block的三种状态:
  1. _NSConcreteGlobalBlock全局静态;
  2. _NSConcreteStackBlock栈保存,函数作用域外销毁;
  3. _NSConcreteMallocBlock堆保存,retain == 0销毁

    推荐阅读