美文网首页
iOS中__block底层原理是怎么样的

iOS中__block底层原理是怎么样的

作者: guoguojianshu | 来源:发表于2019-05-08 12:09 被阅读0次

    我们都知道block是会对申明它的范围内,所有变量都可以为其捕获的。这也就是说,那个范围内的全部变量,在块里依然可用的。但是不能对捕获的变量进行修改,除非加上__block的标志才可以进行修改,这个底层是怎么回事呢?

    先对基本数据类型进行查看

    • 1没有使用__block时候的情况
     int num = 10;
        
        NSLog(@"初始化时候的指针 %p",&num);
        void (^ myBlock)(void) = ^{
            NSLog(@"block中的指针%p",&num);
        };
        myBlock();
        NSLog(@"被block捕获后的指针%p",&num);
    

    打印结果为

    2019-05-08 11:02:58.925066+0800 block[58634:10234102] 初始化时候的指针 0x7ffeef5cb9ec
    2019-05-08 11:02:58.925222+0800 block[58634:10234102] block中的指针0x600000396180
    2019-05-08 11:02:58.925309+0800 block[58634:10234102] 被block捕获后的指针0x7ffeef5cb9ec
    

    1.如何确定指针是在栈中,还是在堆中呢,看指针的大小,因为栈中的指针是很大的,是从高地址开始分配的,堆中的指针是从低地址开始分配的;
    或者是把这些16进制的指针转为10进制,然后用大指针数减去小指针数,获得字节差,再除以两次1024,可以得到多少M的空间,因为堆地址要小于栈地址,又因为iOS中一个进程的栈区内存只有1M,Mac也只有8M,显然num已经是在堆区了。

    注意:但是最后的指针又回到栈了。

    • 2 使用__block表示后
     __block  int num = 10;
        
        NSLog(@"初始化时候的指针 %p",&num);
        void (^ myBlock)(void) = ^{
            NSLog(@"block中的指针%p",&num);
        };
        myBlock();
        NSLog(@"被block捕获后的指针%p",&num);
    

    打印结果

    2019-05-08 11:34:28.594960+0800 block[59001:10269363] 初始化时候的指针 0x7ffee29699e8
    2019-05-08 11:34:28.595104+0800 block[59001:10269363] block中的指针0x6000001f4d38
    2019-05-08 11:34:28.595193+0800 block[59001:10269363] 被block捕获后的指针0x6000001f4d38
    

    有__block标识的,最后的指针也会在堆中,
    总结:加入了__block的表示后,栈中的指针地址永久的被copy到堆中了,不加入__block时候,只是在block内部时候会被暂时的从栈中被copy到堆中,等block结束后又回到栈中了,因为block对象布局中有copy方法,所以可以进行copy操作

    对对象的情况

     NSMutableString * mString = [NSMutableString stringWithString:@"xiaoli"];
        NSLog(@"初始化时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
        void(^myBlock)(void) = ^{
            mString.string = @"xiaowang";
            NSLog(@"在block中的时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
    
        };
        myBlock();
        NSLog(@"在block执行完之后的时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
    

    打印结果

    2019-05-08 12:02:30.881439+0800 block[59318:10294124] 初始化时候 mString指向堆中的地址0x6000004fb180
     mString在栈中的指针地址0x7ffee95b09e8 mString = xiaoli
    2019-05-08 12:02:30.881615+0800 block[59318:10294124] 在block中的时候 mString指向堆中的地址0x6000004fb180
     mString在栈中的指针地址0x6000004fbfb0 mString = xiaowang
    2019-05-08 12:02:30.881698+0800 block[59318:10294124] 在block执行完之后的时候 mString指向堆中的地址0x6000004fb180
     mString在栈中的指针地址0x7ffee95b09e8 mString = xiaowang
    

    加入__block表示后

    __block  NSMutableString * mString = [NSMutableString stringWithString:@"xiaoli"];
        NSLog(@"初始化时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
        void(^myBlock)(void) = ^{
            mString.string = @"xiaowang";
            NSLog(@"在block中的时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
    
        };
        myBlock();
        NSLog(@"在block执行完之后的时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
    

    打印结果

    2019-05-08 12:06:47.865743+0800 block[59378:10299298] 初始化时候 mString指向堆中的地址0x600002507a20
     mString在栈中的指针地址0x7ffeeae199e8 mString = xiaoli
    2019-05-08 12:06:47.865886+0800 block[59378:10299298] 在block中的时候 mString指向堆中的地址0x600002507a20
     mString在栈中的指针地址0x6000025079b8 mString = xiaowang
    2019-05-08 12:06:47.866087+0800 block[59378:10299298] 在block执行完之后的时候 mString指向堆中的地址0x600002507a20
     mString在栈中的指针地址0x6000025079b8 mString = xiaowang
    

    相关文章

      网友评论

          本文标题:iOS中__block底层原理是怎么样的

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