OC Block 其实功能就类似C语言的函数指针,js中的闭包之类的。把代码块当做一个变量就行操作,有自己的变量和作用域。

简单看一下Block的语法和可能出现的问题:

Block语法:

block语法相对宽松,很多部分都可以省略,常规上我们实现一个block需要有以下几个部分

^ 返回值类型 参数列表 表达式

例如

    ^int (int count){return count+;};//返回值为int 参数为int 表达式为 count+1;
^void (void){NSLog(@"void");}; //返回值为void 参数void 表达式为 NSLog(@"void");

可以看到语法相对简单,而且返回值类型可以省略那么以上两个block就变

    ^(int count){return count+;};
^(void){NSLog(@"void");};

如果不适用参数,那么返回值列表也可以省略

    ^(int count){return count+;};
^{NSLog(@"void");};

Block类型变量

Blcok类型的变量可以接受对应的Block,上例中两个Block就需要以下两种Block类型变量接收

    int (^intBlock)(int) = ^(int count){return count+;};
void (^voidBlock)(void) = ^{NSLog(@"void");};

上例中,可以看到变量定义格式

返回值类型 (^变量名称) (返回值类型)

如果嫌这种定义方式麻烦的话,可以使用typedef来简化定义方式

    typedef int (^typedefBlock) (int);
typedefBlock block = ^(int count){return count+;};

截获变量值

Block中,可以使用调用Block之前的变量的值,例如

    int a = ;
int (^intBlock)(int) = ^(int count){return count+a;};
NSLog(@"%d",intBlock());
-- ::53.393 Dispatch[:]

可以看到输出结果是10,说明intBlock截获了变量a的值。

但是如果我们想要修改a的值,就会出现错误可以自己尝试一下。

想要修改需要在变量前添加__block修饰符,说明该变量在block中是可以被修改的。

    __block int a = ;
int (^intBlock)(int) = ^(int count){a = ; return count+a;};
NSLog(@"%d",intBlock());
-- ::11.629 Dispatch[:]

输出结果为8,说明已经被我们修改了。

同样的道理,对已OC对象来说也是,如果调用方法使用该变量可以,但是对变量进行赋值操作就需要加上__block修饰符。

Block循环引用

循环引用出现条件,该对象持有Block的成员属性,同时在Block中使用self。这样会造成Block和对象之间的相互引用,互相都无法释放,形成内存泄露。

@interface ViewController ()
{
voidBlock _voidBlock;
} - (void)viewDidLoad {
[super viewDidLoad]; // __block int a = 5;
_voidBlock = ^{NSLog(@"%@",self);};
_voidBlock(); }

这样写编译去会提示我们self的强引用在Block中使用。

还有一种,如果我们在Block中使用了成员属性,同样会造成内存泄露。因为成员属性是self指针指向的对象,还是在Block中持有了self。

__weak
为了避免这样的情况发生,我们再上面的例子中稍微修改一下

- (void)viewDidLoad {
[super viewDidLoad]; // __block int a = 5;
__weak ViewController *temp = self;
_voidBlock = ^{NSLog(@"%@",temp);};
_voidBlock(); }

使用弱引用对象就能很好的避免这种情况。

再有就是用__block也能够避免循环。

- (void)viewDidLoad {
[super viewDidLoad]; // __block int a = 5;
__block ViewController *temp = self;
_voidBlock = ^{NSLog(@"%@",temp); temp = nil;};
_voidBlock(); }

注意这样写必须调用该Block,执行Block代码才行,如果不执行还是会造成内存泄露。

最新文章

  1. 【每日一linux命令6】命令中的命令
  2. MATLAB 绘图时的相关心得
  3. Web 开发人员必备的12款 Chrome 扩展程序
  4. 与你相遇好幸运,The Moe Node.js Code Style Guide
  5. java获取获得Timestamp类型的当前系统时间
  6. 机器学习实战——k-邻近算法:约会网站
  7. PostgreSQL 8.4.1
  8. bzoj 1034 [ZJOI2008]泡泡堂BNB(贪心)
  9. mysql查找重复
  10. winform代码反编译后图片等资源文件恢复解决方案
  11. WINDOWS批处理命令使用大全
  12. View not attached to window manager
  13. mybatis CRUD
  14. 设计模式的征途—15.观察者(Observer)模式
  15. golang channel
  16. JS中创建多个相同的变量出现的问题
  17. Map、Set使用过程中可能出现的问题
  18. redis(一)
  19. [Spring MVC] 表单提交日期转换问题,比如可能导致封装实体类时400错误
  20. Oracle11g温习-第十三章:索引

热门文章

  1. mysql中文乱码归纳总结
  2. C#学习笔记_08_面向对象
  3. BZOJ 1631 Usaco 2007 Feb. Cow Party
  4. PAT 1099. Build A Binary Search Tree (树的中序,层序遍历)
  5. vue组件 $children,$refs,$parent的使用详解
  6. ganglia问题小结
  7. bootstrap下的双选时间插件使用方法
  8. 【ACM】hdu_zs3_1006_AB_201308101123
  9. A. Treasure Hunt Codeforces 线性代数
  10. hibernate之单表映射