美文网首页
__block的一些思索总结

__block的一些思索总结

作者: 云无心 | 来源:发表于2018-08-13 16:20 被阅读20次

    参考链接 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;
    

    相关文章

      网友评论

          本文标题:__block的一些思索总结

          本文链接:https://www.haomeiwen.com/subject/uysubftx.html