OC对象 - Block-对象类型的auto变量

OC对象 - Block-对象类型的auto变量

1. Block内部访问了对象类型的auto变量

block内部访问了对象类型的auto变量时,此时block可能在栈上,也可能在堆上不同类型的block所表现的动作是不一样的

1.1 基础代码

创建一个ZSXPerson类,在- (void)dealloc打印一下,这样我们可以清楚看到ZSXPerson对象什么时候销毁

less 复制代码
@interface ZSXPerson : NSObject

@end

@implementation ZSXPerson

- (void)dealloc {
    [super dealloc];
    NSLog(@"ZSXPerson --- %s", __func__);
}

@end

main.m

csharp 复制代码
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        {
            ZSXPerson *person = [[ZSXPerson alloc] init];
        }
        NSLog(@"-----");
    }
    return 0;
}

{}内,初始化一个ZSXPerson对象,然后在在{}外打了断点

可以看到person对象出了{}马上销毁

接下来我们在此基础上,尝试不同 block 对person对象销毁时机的影响

1.2 Block访问person对象

增加一个block,内部访问person对象

ini 复制代码
ZSXBlock block;
{
    ZSXPerson *person = [[ZSXPerson alloc] init];
    person.age = 10;
    
    block = ^ {
        NSLog(@"%d", person.age);
    };
    
}
NSLog(@"block - %@", [block class]);
NSLog(@"-----");

此时断点停留在{}之后,按理说 person 已经出了作用域了,但实际却没有销毁

我们断点继续往下走 出了@autoreleasepool之后,person才销毁。这时候刚好 block 也已经出了作用域,block是会销毁的。因此,block里面对person有强引用,所以出了第一个{}的时候,虽然person已经走出作用域,但是此时block还在作用域内,它还持有person,所以person并不会释放

1.2.1 查看底层实现

block访问对象类型的auto变量后

  • block结构体中持有person成员的指针
  • __main_block_desc_0结构体中多了copydispose两个函数。这两个函数是用来管理block所持有变量的持有关系的

因为block里面持有了对象,对象本身在内存中是通过引用计数来管理内存的,因此block也需要对其负责内存管理

1.3 NSStackBlock类型block访问对象类型

NSStackBlock类型block本身就是随时可能释放的,所以NSStackBlock类型的block没有必要强持有访问对象

1.3.1 修改代码

代码中我们不使用strong变量接收block,这时候的block就是NSStackBlock类型的

ini 复制代码
ZSXBlock block;
{
    ZSXPerson *person = [[ZSXPerson alloc] init];
    person.age = 10;
    
    ^ {
        NSLog(@"%d", person.age);
    };
}
NSLog(@"block - %@", [block class]);
NSLog(@"-----");

打印结果: person出了作用域马上就释放了,因此可以说明这时候的block并没有持有person

2. 总结

block内部访问了对象类型的auto变量时

  • 如果block是在栈上,将不会对auto变量产生强引用

  • 如果block被拷贝到堆上

    1. 会调用block内部的copy函数
    2. copy函数内部会调用_Block_object_assign函数
    3. _Block_object_assign函数会根据auto变量的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用
  • 如果block从堆上移除

    1. 会调用block内部的dispose函数
    2. dispose函数内部会调用_Block_object_dispose函数
    3. _Block_object_dispose函数会自动释放引用的auto变量(release)

@oubijiexi

相关推荐
tan77º37 分钟前
【项目】分布式Json-RPC框架 - 项目介绍与前置知识准备
linux·网络·分布式·网络协议·tcp/ip·rpc·json
正在努力的小河3 小时前
Linux设备树简介
linux·运维·服务器
荣光波比3 小时前
Linux(十一)——LVM磁盘配额整理
linux·运维·云计算
LLLLYYYRRRRRTT4 小时前
WordPress (LNMP 架构) 一键部署 Playbook
linux·架构·ansible·mariadb
轻松Ai享生活4 小时前
crash 进程分析流程图
linux
大路谈数字化6 小时前
Centos中内存CPU硬盘的查询
linux·运维·centos
luoqice6 小时前
linux下查看 UDP Server 端口的启用情况
linux
倔强的石头_7 小时前
【Linux指南】动静态库与链接机制:从原理到实践
linux
赏点剩饭7788 小时前
linux中的hostpath卷、nfs卷以及静态持久卷的区别
linux·运维·服务器
神鸟云8 小时前
DELL服务器 R系列 IPMI的配置
linux·运维·服务器·网络·边缘计算·pcdn