面试宝点

聊聊block

2021-03-04  本文已影响0人  冬ge

block本质

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

一个block 底层实现

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

block类型

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

block 类型

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

底层结构图

** 为什么在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;
}
外部局部变量无法修改
__block  int age = 10;
        tsBlock block = ^{
            
            age = 20;
            NSLog(@"age is %d", age);
        };
        
        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属性修饰符词为什么是copy,使用block哪些注意点
block在修改NSmutablearray用不用加上 __block
上一篇下一篇

猜你喜欢

热点阅读