聊聊block

作者: 冬ge | 来源:发表于2021-03-04 13:23 被阅读0次

block本质

  • block本质上也是一个OC对象,它内部也有个isa指针
  • block是封装了函数调用以及函数调用环境的OC对象

如下例子 脑海中要有此图。

一个block 底层实现

block 就是一个对象, 有一个isa指针, funcptr 存放代码地址, 有外部局部变量
补充内存分布知识:
全局变量 存放数据段,
局部变量 栈区间
实例对象 堆区间
类对象 数据段 >

block类型

block 内存其实在栈上的, 但我们常常需要对其持有长时间,用copy修饰。 从栈区间拷贝到堆区间。栈区间自动释放后, 不会影响堆区间。
在ARC模式下 编译器会自动将栈上的block内存copy到堆区间上.
1. block作为函数参数返回。
2. 被 strong指针修饰。
3 . GCD 参数
4. 作为Cocoa API 中方法名有usingBlock方法参数时

block 类型
  • 栈空间上的block 不能持有外部的对象。不能保住对象的命
    堆空间上的block 可以引用外部对象。 retain计数+1,release -1 可以 保住对象的命

  • 如果block 在栈上, block内部不会对外部的auto变量强引用

  • 在堆上, block内部自动进行copy工作 从底层结构体 main_block_desc_0 内部就可以看出 会自动调用一个 main_block_copy 调用一个 block_object_assgin会根据atuo变量的修饰符(__strong __weak ,_unsafe_unretained)做出操作 类似于retain(形成强引用, 若引用)。

  • 如果block从堆中移除, 会调用dispose函数
    dispose函数内部会调用_block_object_dispose函数, 会自动释放引用的auto变量, 类似于release.

为什么我们常用weak修饰block呢 也就是说。 当对象想死的时候 。 block不会强行占有对象。 对象可以死去。哈哈哈

底层结构图
  • oc 转C++命令
    clang -x objective-c -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk main.m

** 为什么在block内部不能修改局部外部变量呢?
内部结构体 属性age 和block 在两个函数里。 在block函数里访问不到外部局部变量

int main(int argc, const char * argv[]) {
    @autoreleasepool {
      
        int age = 10;
        tsBlock block = ^{
            
            //age = 20;
            NSLog(@"age is %d", age);
        };
        
        block();
        
    }
    return 0;
}
外部局部变量无法修改
  • 1.static 修饰局部变量(一般不采用.内存无法释放) 可以在如下图片中看到 age前边加了指针 就可以访问了


    staic 修饰后
__block  int age = 10;
        tsBlock block = ^{
            
            age = 20;
            NSLog(@"age is %d", age);
        };
        
        block();
        
    }
  • 2.__block 修饰局部变量. 可以解决无法修改局部变量问题
    看内部c++ 代码. 多了一个包装结构体block
    block内部有一个指针 指向结构体, 通过指针找到那个结构体内存,
    把结构体里的变量改掉.


    __block修饰后
__block的 _forwarding指针

3.block 修饰对象.

int main(int argc, const char * argv[]) {
    @autoreleasepool {
       
      __block  MJPerson *p = [[MJPerson alloc] init];
       
        tsBlock block = ^{
            
            NSLog(@"%@", p);
        };
        
        block();
        
    }
    return 0;
}
修饰对象 block
block

循环引用问题

int main(int argc, const char * argv[]) {
 @autoreleasepool {
    
     MJPerson *p = [[MJPerson alloc] init];
    
     p.block = ^{
        
         NSLog(@"%@", p.name);
         
     };
     
     NSLog(@"111111");
     
 }
 return 0;
}
[循环引用)] 循环引用

block内部结构体生成一个强引用的指针 指向类对象, 对象里边有个变量block 会访问 block. 也就是有个强引用指针.
本质:两个强引用, 你引用我. 我引用你. 导致无法释放

解决循环引用问题
      不会产生强引用, 不安全, 指向的对象销毁, 指针存储的地址值不变.
           1.   __unsafe_unretained  MJPerson *p = [[MJPerson alloc] init];
               不会产生强引用.指向对象销毁时候,会自动让置为 nil
           2.  __weak MJPerson *weakPerson = p;
                p.block = ^{
        
                    NSLog(@"%@", p.name);
        
                };
        
                NSLog(@"111111");

3.说说第三种用block解决方式 对象 - block - block变量. block变量里边有一个指针指向对象. 形成三者紧密联系. 当我们把block变量里边的这个对象指针置位nil. 就解决了引用. 但不是最好的方式.

解决循环引用 MRC 解决block
block 本质是什么

-封装了函数调用以及调用环境的oc对象

__block修饰符 干了什么
  • __block可以用于解决block内部无法修改auto变量值得问题
    不能修饰全局变量,静态变量(static)
    -编辑器会将__block变量包装成一个对象
block属性修饰符词为什么是copy,使用block哪些注意点
  • copy 把内存拷贝到堆上.
block在修改NSmutablearray用不用加上 __block
  • 不用. 加上后.反而内部结构变复杂.

相关文章

  • 聊聊block

    block本质 block本质上也是一个OC对象,它内部也有个isa指针 block是封装了函数调用以及函数调用环...

  • 来聊聊Block(二)

    上一篇 文章 简要解释了Block的基本概念,打一些基础,从而能够更好的了解关于编程语言中类似于Objective...

  • 来聊聊Block(一)

    作为iOS-Advanced第一篇,我们来聊聊Block,这是一个Objective-C语言里开发者非常喜欢的语法...

  • 聊聊OC中的Block

    对于block中的全局变量和静态变量,block中改变量的地址不发生变化;对于一般变量,block中会对此变量进行...

  • iOS之解耦机制

    聊聊delegate, block, notification, KVO 一 高内聚低耦合是软件设计永恒的主题之一...

  • iOS开发之Block原理探究

    Block概述 Block本质 Block调用 Block分类 Block循环引用 Block原理探究 Block...

  • block的使用

    定义block 返回类型 (^block名称)(参数) = ^(){block内容}; 调用block block...

  • Block 02 - __block

    Block 02 - __block __block 的作用 __block 可以解决 Block 内部无法修改 ...

  • iOS面试之Block大全

    Block Block内容如下: 关于Block 截获变量 __block修饰符 Block的内存管理 Block...

  • iOS面试之Block模块

    Block Block内容如下: 关于Block 截获变量 __block修饰符 Block的内存管理 Block...

网友评论

    本文标题:聊聊block

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