Objective-C——Block

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

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

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

Block语法:

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

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

例如

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

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

^(intcount){returncount+1;};^(void){NSLog(@"void");};

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

^(intcount){returncount+1;};^{NSLog(@"void");};

Block类型变量

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

int(^intBlock)(int) = ^(intcount){returncount+1;};void(^voidBlock)(void) = ^{NSLog(@"void");};

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

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

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

typedefint(^typedefBlock) (int);

typedefBlock block= ^(intcount){returncount+1;};

截获变量值

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

inta =5;int(^intBlock)(int) = ^(intcount){returncount+a;};

NSLog(@"%d",intBlock(5));2015-08-0217:25:53.393Dispatch[9970:3096937]10

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

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

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

__blockinta =5;int(^intBlock)(int) = ^(intcount){a =3;returncount+a;};

NSLog(@"%d",intBlock(5));2015-08-0217:33:11.629Dispatch[10118:3136172]8

输出结果为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代码才行,如果不执行还是会造成内存泄露。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航