编译器和运行时让block中引用的所有变量都被保存下来,以备在block的所有副本的生命周期中使用。
- (void)block1 { int (^myTest)(int) = ^(int num){ return num * num; }; NSLog(@"double: %d",myTest(9)); }
__block
声明 - (void)block2 { NSArray *stringsArray = @[ @"string 1", @"String 21", // <- @"string 12", @"String 11", @"Strîng 21", // <- @"Striñg 21", // <- @"String 02" ]; NSLocale *currentLocale = [NSLocale currentLocale]; __block NSUInteger orderedSameCount = 0; NSArray *diacriticInsensitiveSortArray = [stringsArray sortedArrayUsingComparator:^(id string1, id string2) { NSRange string1Range = NSMakeRange(0, [string1 length]); NSComparisonResult comparisonResult = [string1 compare:string2 options:NSDiacriticInsensitiveSearch range:string1Range locale:currentLocale]; if (comparisonResult == NSOrderedSame) { orderedSameCount++; } return comparisonResult; }]; NSLog(@"diacriticInsensitiveSortArray: %@", diacriticInsensitiveSortArray); NSLog(@"orderedSameCount: %lu", (unsigned long)orderedSameCount); }
- (void)block3 { void (^variadicParams)(NSString*, ...) = ^(NSString *format, ...) { id eachObject; va_list argumentList; // va_list是指向变量列表的指针 if (format) { // 第一个参数并不是变量列表中的一个 NSMutableArray *tmpArray = [NSMutableArray arrayWithObject:format]; va_start(argumentList, format); // 初始化va_list,并让它指向传入的参数(format)后面紧跟的第一个参数 while ((eachObject = va_arg(argumentList, id)) != nil){ // va_arg,取出列表中的下一个参数。必须指明参数的类型(这样va_arg才能知道该给它分配多少空间) [tmpArray addObject:eachObject]; // 不会把任何nil对象添加到tmpArray中 } va_end(argumentList); // 释放va_list这个数据结构所持有的任何内存 NSLog(@"variadic params: %@",tmpArray); } }; variadicParams(@"11",@"22",@"333",@"666",nil); // Calios:这里最后一个参数必须传nil,args必须有最后一个结尾,否则是无法判断的。But,why? }
NSInteger CounterGlobal; // Calios:It throws out error for not finding CounterGlobal if extern is added. But, why? static NSInteger CounterStatic; - (void)block4 { NSInteger localCounter = 42; __block char localCharacter; void (^aBlock)(void) = ^(void) { ++CounterGlobal; ++CounterStatic; CounterGlobal = localCounter; // localCounter fixed at block creation localCharacter = 'a'; // sets localCharacter in enclosing scope }; ++localCounter; // unseen by the block localCharacter = 'b'; aBlock(); // execute the block // localCharacter now 'a' }
如果你在一个方法的实现中使用了block:
如果你使用了实例变量的引用,那么就对 self 产生了强引用;
如果你使用了实例变量的值,那么就对 该变量 产生了强引用。
(void)block5
{
void (^doSomethingWithObject)(id) = ^(id var){
NSLog(@”do something: %@”,var);
};
dispatch_queue_t queue = dispatch_queue_create(“com.calios.BlockSample.someQueue”, DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{ // dispatch_async()是将block拷贝到指定的queue中,而复制操作(Block_copy())会将block移动到堆上。
// instanceVariable is used by reference, a strong reference is made to self
doSomethingWithObject(instanceVariable);
});
id localVariable = instanceVariable; dispatch/_async(queue, ^{ /* localVariable is used by value, a strong reference is made to localVariable (and not to self). */ doSomethingWithObject(localVariable); }); }
block字面量(即^{ … })是代表这个block的局部栈数据结构的地址。因此,局部栈数据结构的作用于就是仅限于大括号中的语句,所以你应 避免 向下面这样使用block。
- (void)block6 { dontDoThis(); dontDoThisEither(); } void dontDoThis() { void (^blockArray[3])(void); // an array of 3 block references for (int i = 0; i < 3; ++i) { blockArray[i] = ^{ printf("hello, %d/n", i); }; // WRONG: The block literal scope is the "for" loop. } } void dontDoThisEither() { void (^block)(void); int i = arc4random() % 1024; if (i > 1000) { block = ^{ printf("got i at: %d/n", i); }; // WRONG: The block literal scope is the "then" clause. } // ... }