__block
来源:互联网 发布:快搜极速浏览器mac 编辑:程序博客网 时间:2024/05/18 14:15
- Block是什么?
- Block的功能
- Block的用法
- 如何声明和定义Block
- 直接使用Block
- Block和Cocoa
- block和变量之间的关系
- 关于 __block 的进一步讨论
- __block 和Object C对象之间的关系
- __block 和C++对象之间的关系
Block是什么?
Block是C语言的一个语法特性,同时也是C语言的运行时特性,它很像C中的函数指针,因为你可以像使用函数指针一样的去使用block对象;它也很像C++中的函数对象,因为除了要执行的代码,block还可以携带和block绑定的状态信息。
因此,block是一个对象,这个对象里包含了要执行的代码片段以及一些状态信息。
MacOSX 10.6和iOS 4.0以上版本的Xcode开发包提供了对block的支持。
Block的功能
block是一片具有以下特性的内联代码片段集合:
- 可以像函数一样有类型参数;
- 可以声明或推算出一个返回类型;
- 可以访问和block定义在同一个词法范围里的变量(即Status);
- 可以修改同一个词法范围里的变量;
- 同一个词法范围的block之间可以共享变量和变量的修改结果;
- 当栈被摧毁后,栈里的block依旧可以保持状态信息;
Block的用法
作为一个自包含的代码片段,由于以下特性,block很适合作为回调函数的替代方案:
- 你可以在方法的下上文中,调用block的地方直接编写构成block的代码片段;
- block可以访问局部变量;
如何声明和定义Block
你可以通过^操作符定义一个block类型的变量,用{}来圈定block的代码片段,如下图所示:
再次声明:block可以访问和block定义在同一个词法范围里的变量。
int multiplier = 7;int (^myBlock)(int) = ^(int num) { return num * multipiler; }printf("%d", myBlock(3)); // prints "21"
直接使用Block
在更多的时候,你并不需要定义自己的Block类型,而是在API中直接编写block代码片段,例如:qsort_b。
char *myCharacter[3] = { "safari", "ie", "chrome" };qsort_b(myCharacter, 3, sizeof(char *), ^(const void *l, const void *r) {char *left = *(char **)l; char *right = *(char **)r; return strncmp(left, right, 1);});
Block和Cocoa
Cocoa framework中很多方法使用了Block作为其参数(尽管也有对应的callback版本,但还是推荐使用 block版本)。在动画以及集合遍历方面,block很常见。
NSArray *stringsArray = [NSArray arrayWithObjects:@"string 1", @"String 21", @"string 12", @"String 11", @"String 02", nil];static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch | NSNumericSearch |NSWidthInsensitiveSearch | NSForcedOrderingSearch;NSLocale *currentLocale = [NSLocale currentLocale];NSComparator finderSortBlock = ^(id string1, id string2) { NSRange string1Range = NSMakeRange(0, [string1 length]); return [string1 compare:string2 :comparisonOptions options :string1Range range :currentLocale];};NSArray *finderSortArray = [stringsArray locale :finderSortBlock];NSLog(@"finderSortArray: %@", finderSortArray); sortedArrayUsingComparat or
block和变量之间的关系
这一部分涉及内存管理相关的内容,为了正确的使用block,理解并记住它们,很重要:
在一个block代码片段的内部,你可以使用三种不同类型的变量(就像你在函数里一样):
- 全局变量(包括static locals);
- 全局函数(尽管这并不是变量=。=);
- 在包含block的词法范围内的局部变量;
当在一个Block里使用变量时,应遵循以下规则:
- 在包含block的词法范围里的栈局部变量,在block内部是常量,只能只读访问。这些局部变量的值即block执行时,局部变量的值。在多层内嵌的block中,
局部变量的值,取最内层词法范围里,局部变量的值;
- 被声明为__block存储类型的局部变量通过引用传递给block,因此是mutable的;在__block类型的局部变量的有效范围内,对该局部变量的修改,会在该有效范围内的所有block范围内生效;
- 定义在block内部的局部变量,和函数内部的局部变量法则相同;
正确的:
__block int x = 123;void (^printXandY)(int) = ^(int y) {("%d %d\n", x, y);};printXandY(456); printf
错误的:
int x = 123;void (^printXandY)(int) = ^(int y) {= x + y; // ERROR HERE!!! x should be __block x ("%d %d\n", x, y);};printXandY(456); printf
关于__block的进一步讨论
- __block是只针对局部变量生效的一种描述变量存储类型的关键字,因此__block类型的变量都是栈变量;
- __block类型的变量在其定义的语法范围里,和该范围内的所有block共享存储空间,当block在被复制到heap区域时,同区域内的__block变量占用的内存不会随着退栈而销毁;
- 出于优化的考虑,栈中的block对象最开始和一般的栈局部变量是相同的,当使用Block_copy对block进行复制时,才被拷贝到heap区域;
- __block变量不能是一个可变长数组;
下面这个例子用于展示,各种类型的变量与__block之间的交互:
extern NSInteger CounterGlobal;static NSInteger CounterStatic;{NSInteger localCounter = 42; char localCharacter; __block void (^aBlock)(void) = ^(void) { ++CounterGlobal; ++CounterStatic; CounterGlobal = localCounter; // localCounter fixed at block creation = 'a'; // sets localCharacter in enclosing scope localCharacter }; ++localCounter; // unseen by the block = 'b'; localCharacter (); // execute the block aBlock // localCharacter now 'a'}
__block和Object C对象之间的关系
如果,你在一个方法的实现里,使用了__block,则:
- 通过引用的方式访问对象的,self被retain;
dispatch_async(queue, ^{
doSomethingWithObject
- 通过值访问对象的,被访问的对象被retain;
id localVariable = instanceVariable;dispatch_async(queue, ^{
doSomethingWithObject
__block和C++对象之间的关系
需要注意两点:
- 把一个基于栈的C++对象变成一个__block类型的时候,要调用类的copy constructor;
- 在block内部使用栈中的C++对象时,要调用栈的const copy constructor;
- __block
- __block
- __Block
- iOS __block
- __block相关
- __weak && __block
- __block __weak
- __block : 理解
- OC __block
- 关于 __block storage modifier
- 什么时候该用__block
- Block 3:__block说明符
- __block的作用
- __block的使用
- __weak与__block区别
- __block,__weak区别
- __weak与__block区别
- iOS - __weak&&__block
- js 数组Array用法
- nyoj 117 归并求逆序数
- 测试must_add(l_t_s)_(e_t)_no_tec_rec
- RabbitMQ 安装配置与管理
- android常见错误总结
- __block
- Android中内容观察者的使用---- ContentObserver类详解
- WindowManage返回无效
- 常常出现的loadrunner问题
- 字符串hash算法比较
- 从HTML到CSS再到Javascrtip:人生的历练
- 2012-11-13
- C#动态调用webservice方法
- asp.net 六大对象之Request、Response