编译器和运行时让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.
}
// ...
}