参考链接 https://www.jianshu.com/p/ee9756f3d5f6
命令: -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 ViewController.m
1. 常量
- (void)test1 {
__block int a = 1;
int b = 2;
NSLog(@"1a----%p %d",&a,a);
NSLog(@"1b----%p %d",&b,b);
self.blockkk = ^(void){
NSLog(@"block 2a----%p %d",&a,a);
NSLog(@"block 2b----%p %d",&b,b);
};
NSLog(@"3a----%p %d",&a,a);
NSLog(@"3b----%p %d",&b,b);
b = 89757;
a = 89758;
self.blockkk();
NSLog(@"4a----%p %d",&a,a);
NSLog(@"4b----%p %d",&b,b);
}
输出为
__block[68513:7304153] 1a----0x7ffee5b45448 1
__block[68513:7304153] 1b----0x7ffee5b4542c 2
__block[68513:7304153] 3a----0x604000226558 1
__block[68513:7304153] 3b----0x7ffee5b4542c 2
__block[68513:7304153] block 2a----0x604000226558 89758
__block[68513:7304153] block 2b----0x60400044d378 2
__block[68513:7304153] 4a----0x604000226558 89758
__block[68513:7304153] 4b----0x7ffee5b4542c 89757
可以很清楚的看到, 被__block
修饰的在之后引用,地址已经变了 实际上,我们使用clang查看之后有可以发现实际上是这样的, a的使用已经是使用的block里面结构体的地址
b = 89757;
(a.__forwarding->a) = 89758;
然后,被__block
修饰的 之后调用是 (a.__forwarding->a)
其实已经不是访问原地址了
2. 对象
其实对象是一样的逻辑. 但是我在打印对象使用的 %@
,实在是犯了最简单的错误, 实际上使用%@
是打印其中的值, 所以最好使用%p
吧 哈哈 别像我一样搞半天头疼
- (void)test5
{
__block FSPerson *blockP = [[FSPerson alloc] init];
FSPerson *p = [[FSPerson alloc] init];
NSLog(@"1--- %p --- %p",&p,&blockP);
void (^myBlock)(void) = ^{
blockP.name = @"89757";
p.name = @"89758";
NSLog(@"2--- %p --- %p",&p,&blockP);
};
NSLog(@"3--- %p --- %p",&p,&blockP);
myBlock();
NSLog(@"4--- %p --- %p",&p,&blockP);
}
打印为
__block[68726:7328927] 1--- 0x7ffeea7d0418 --- 0x7ffeea7d0448
__block[68726:7328927] 3--- 0x7ffeea7d0418 --- 0x60000025a668
__block[68726:7328927] 2--- 0x600000252e60 --- 0x60000025a668
__block[68726:7328927] 4--- 0x7ffeea7d0418 --- 0x60000025a668
总结
不被__block
修饰的, 实际上后面在使用 还是跟前面一样地址, 而block内部实际上拷贝到了堆上 , 没有为其建立结构体 , 而且 值拷贝.
使用__block
修饰的, 实际上block后面的访问都是(a.__forwarding->a) = 89758;
也就是, 实际上跟之前的地址已经不同了,并且在结构体内, 给予了内存, 所以也可以对其修改.
个人认为,__block
需要封装对象,肯定是消耗性能并且更加的耗时, 所以苹果给出了2中解决办法,不用__block
值拷贝不可修改,使用__block
的话, 就是完整复制一份, 这样可以修改.同时 这是对 block是封装了函数及其函数调用的完美解释..
b = 89757;
(a.__forwarding->a) = 89758;