块(Blocks)

2015-12-21  本文已影响54人  ssdfsj

《Objective-C程序设计第四版中文翻译》对Blocks介绍得有点少,对block还是糊里糊涂的,真用到的时候有点迷惘。

块是对C语言的一种扩展,优势:能让系统分配给其他处理器或者应用的其他线程执行,通常用于配合GCD写多线程。看起来像函数 ,跟函数相同之处:可以像函数一样给它传值,接收返回值;不同之处:块定义在函数或者方法内部,能访问在函数或者方法范围内块之外的任何变量。访问只能读取变量的值,如果需要改变,要在定义块的时候使用块修改器声明。

块是以插入字符“^”开头为标识的,下面是块的定义和调用。

void (^print_message)(void) =

^(void) {

NSLog(@"Programming is fun.");

}; //定义

print_message();//调用

但是一般你看到的是这样,没有名字的块,只有传入的参数和块内的具体代码。

[reader setCompletionWithBlock:^(NSString *resultAsString) {

        webUrl = resultAsString;

        [self ReadyToDownload];

       [wSelf.navigationController popViewControllerAnimated:YES];

   }];

如果在定义变量的时候使用__block , 如 __block int n = 1;则说明这个变量能在代码块内被改变。

但是我还是不懂这个block,那就参考唐巧大牛的博客来做点练习,看能不能自己理解。

1.isa指针,跟对象一样,都有isa指针,用于指向变量或者对象存储的内存地址。

2.flags,用于按 bit 位表示一些 block 的附加信息。

3.reserved,保留变量。

4.invoke,函数指针,指向具体的 block 实现的函数调用地址。

5.descriptor, 表示该 block 的附加描述信息,主要是 size 大小,以及 copy 和 dispose 函数的指针。

6.variables,capture 过来的变量,block 能够访问它外部的局部变量,就是因为将这些变量(或变量的地址)复制到了结构体中。

关于存储位置:在Objective-C语言中,一共有3种类型的block:

(1)_NSConcreteGlobalBlock 全局的静态block,不会访问任何外部变量。

(2)_NSConcreteStackBlock 保存在栈中的block,当函数返回时会被销毁。

 (3)_NSConcreteMallocBlock 保存在堆中的block,当引用计数为0时会被销毁。

参考block的例题说明:

Example B

void exampleB_addBlockToArray(NSMutableArray *array) {

char b = 'B';

[array addObject:^{

printf("%cn", b);

}];

}

void exampleB() {

NSMutableArray *array = [NSMutableArray array];

exampleB_addBlockToArray(array);

void (^block)() = [array objectAtIndex:0];

block();

}

在MRC的时候,block是_NSConcreteStackBlock类型,被创建保存在栈中,一旦所在函数返回,则会被摧毁。所以exampleB_addBlockToArray(array);运行完之后,存在栈上面的变量b就不存在了。

如果把函数改为

void exampleB_addBlockToArray(NSMutableArray *array) {

[array addObject:^{

printf("cn");

}];

}

这样的话,block是_NSConcreteGlobalBlock,全局的静态block,不会访问任何外部变量。不用考虑内存问题。

Example D

typedef void (^dBlock)();

dBlock exampleD_getBlock() {

char d = 'D';

return ^{

printf("%cn", d);

};

}

void exampleD() {

exampleD_getBlock()();

}

这个也是一样,把block返回,但是里面的变量在没有ARC的情况下是函数返回就被销毁的。这个跟函数一样的,那关于传入参数的问题,应该也是一样的。

总结:这样看来,block像一个能运行代码的对象,里面的变量就像在函数里一样,局部变量会在返回的时候被销毁,需要像Example B和D那样使用block,需要ARC,它把所有对象的放在堆上面,包括block,方便管理。而在block里访问block外的变量的话,只是把值copy进block内,需要加上__block关键字,才能把变量地址传进block,在block内进行修改。

参考:谈Objective-C Block的实现-唐巧  , Objective-C Blocks Quiz

上一篇下一篇

猜你喜欢

热点阅读