对于block的使用很多人用过,但是要深入,还有些路要走。
NSString *str =@"text";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"//str is %@",str);---------->1
});
str = @"text1";
NSLog(@"###########str is %@",str);---------->2
对于上面的block,我原以为会先执行1,再执行2或者str打印的值都是text1
其实不然,在block调用外部变量为常量时时,编译器会优化,block里的str会指向常量的地址,由于block有延时,会先顺序执行下面的代码,给str赋值text1,并打印
str为text1,等待0.5秒后,执行block里的打印信息,此时block里的str仍然是指向常量的地址,执行 NSLog(@"//str is %@",str);---------->1.
block里的str跟外面的str指向了栈中不同的常量地址。block外部修改了str的指向,不影响block里面的指向,block是一种指针拷贝,所以指向的目的地址互不影响。
打印如下:
###########str is text1
//str is text
这就是为啥修改block引用的外部变量时要加_block,这时才真正拷贝的str变量的地址。
如果只是在str前加上__block,编译器不会优化block里的变量str,程序如下
__block NSString *str2 =@"text";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"//str2 is %@",str2);
});
str2 = @"text1";
NSLog(@"###########str2 is %@",str2);
###########str2 is text1
//str2 is text1
这是针对局部变量的情况下,如果是全局变量或静态变量,不加block跟加block一样,block是拷贝的变量的地址。