对 block 内存管理的一些看法

本文详细介绍了Block中的循环引用问题及解决方法,包括如何利用__strong、__weak等关键字避免循环引用,并探讨了不同环境下Block的内存管理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先交代一下retain cycle ,和 产生retain cycle后我们应该怎么处理。

1.retain cycle在block中是极易产生,block就是一段可以灵活使用的代码,你可以把它当做变量传递,赋值,甚至可以把它声明到函数体中。更加灵活的是它可以引用它的承载者(即就是block的运行环境),但是这样子就更容易产生retain cycle了 。就是简单说类比 子控件拥有父控件的引用,而父控件也拥有子控件的引用。这样相互引用。就不能形成父控件释放也能将子控件释放。这就造成一个内存泄露。

2.及时打破这种retain cycle ARC :__strong , __weak ,__unsafe_unretained.存在有三个修饰字符,__strong 这要有调用,引用计数就要加1(retain) __unsafe_unretained 赋值给这个变量不会被retain,就是有这个字符修饰的对象,不能保证对象的可靠性。可能已经释放了。留下的只是一个野指针而已。__weak是ios5以后出现的类比与__unsafe_unretained,不同的地方就是。它所持有对象被释放后会自动被赋值为nil。更加安全了。

正如下面的代码就是一个典型的retain cycle    

People *p=[People new];

    p.dosth = ^(){

        [p dosth];

        [p release]; //因为dosth和p是相互持有关系,所以调用release也不能释放掉

    };

1.我们可以这样子处理(自己心里应该清楚,我们不会再次回来调用这个方法了)

People *p=[People new];

    p.dosth = ^{

        [p dosth];

        p.dosth=nil;

        [p release]; //因为dosth和p是相互持有关系,所以调用release也不能释放掉

    };

2.在ARC情况下

 在ARC下, 以下几种情况, Block会自动被从栈复制到堆:

     1.被执行copy方法

     2.作为方法返回值

     3.将Block赋值给附有__strong修饰符的id类型的类或者Blcok类型成员变量时

     4.在方法名中含有usingBlock的Cocoa框架方法或者GDC的API中传递的时候.

利用

__block 将变量的地址考进了栈空间,这样子我们就可以在Block中方便无比的调用最新的变量值了。因为block的空间也是在栈空间的.block内存是在栈上,(不需要程序员管理),当你这个作用域{方法}结束的时候,block被释放了.

 __weak 被__weak修饰的变量,是不会被block retain的,但是也会同时引出提前释放变量的后果

3.在非ARC情况下

只要实现一个对周围变量没有引用的Block,就会显示为是NSGlobalBlock  

如果其中加入了对局部变量的引用,就是NSStackBlock   

如果你对一个NSStackBlock对象使用了Block_copy()或者发送了copy消息,就会得到NSMallocBlock  (0)

1)NSGlobalBlock:retain、copy、release操作都无效;

2)NSStackBlock:retain、release操作无效,必须注意的是,NSStackBlock在函数返回后,Block内存将被回收。即使retain也没用。容易犯的错误是[mutableAarry addObject:stackBlock],(补:在ARC中不用担心此问题,因为ARC中会默认将实例化的Block拷贝到堆上)在函数出栈后,从mutableAarry中取到的stackBlock已经被回收,变成了野指针。正确的做法是先将[stackBlock copy]到堆上,然后加入数组:[mutableAarry addObject:[[stackBlock copy] autorelease]]。支持copy,copy之后生成新的NSMallocBlock类型对象。

3)NSMallocBlock支持retain、release,虽然retainCount始终是1,但内存管理器中仍然会增加、减少计数。copy之后不会生成新的对象,只是增加了一次引用,类似retain;

4)Block_copy与copy等效,Block_release与release等效;

5)对Block不管是retain、copy、release都不会改变引用计数retainCount,retainCount始终是1;

6)尽量不要对Block使用retain操作,不方便管理。

4、Block对objc对象的内存管理

staticObj、instanceObj、localObj、blockObj多种类型obj对象

主要是block被copy时其块中用到的变量的引用计数

1)非ARC

staticObj在内存中的位置是确定的,所以Block copy时引用计数不会改变。

instanceObj在Block copy时并没有直接让instanceObj对象本身引用计数加1,但却让self引用计数加1。所以在Block中可以直接读写instanceObj变量。 

localObj在Block copy时,系统自动增加其引用计数。

blockObj在Block copy时引用计数也不会改变。

使用__block避免循环引用

__block 类 *对象 = self

void(^block)(void)= ^{

[blockSelf doSomething];

};

ARC下

只有在使用local变量时,block会复制指针,且强引用指针指向的对象一次。其它如全局变量、static变量、block变量等,block不会拷贝指针,只会强引用指针指向的对象一次。

block的循环引用,因为block在拷贝到堆上的时候,会retain其引用的外部变量,那么如果block中如果引用了它的宿主对象,那很有可能引起循环引用。如:

self.myblock = ^{

[self doSomething];

};

使用__weak避免循环引用

 

Tips:

内存主要分为

1.栈 - 由编译器自动分配释放  里面的变量通常是局部变量 函数参数等

2.堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 alloc

3.全局区(静态区 static),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束释放 static

People *p;  People *p2 = nil;

4.另外还有一个专门放常量的地方。- 程序结束释放  NSString *lastName = @“xue”;

lastName = @“dkjs”;

5、方法区

转载于:https://www.cnblogs.com/fuunnyy/p/4847511.html

1. 用户与权限管理模块 角色管理: 学生:查看实验室信息、预约设备、提交耗材申请、参与安全考核 教师:管理课题组预约、审批学生耗材申请、查看本课题组使用记录 管理员:设备全生命周期管理、审核预约、耗材采购与分发、安全检查 用户操作: 登录认证:统一身份认证(对接学号 / 工号系统,模拟实现),支持密码重置 信息管理:学生 / 教师维护个人信息(联系方式、所属院系),管理管理所有用户 权限控制:不同角色仅可见对应功能(如学生不可删除设备信息) 2. 实验室与设备管理模块 实验室信息管理: 基础信息:实验室编号、名称、位置、容纳人数、开放时间、负责人 功能分类:按学科(计算机实验室 / 电子实验室 / 化学实验室)标记,关联可开展实验类型 状态展示:实时显示当前使用人数、设备运行状态(正常 / 故障) 设备管理: 设备档案:名称、型号、规格、购置日期、单价、生产厂家、存放位置、责任人 全生命周期管理: 入库登记:管理员录入新设备信息,生成唯一资产编号 维护记录:记录维修、校准、保养信息(时间、内容、执行人) 报废处理:登记报废原因、时间,更新设备状态为 "已报废" 设备查询:支持按名称、型号、状态多条件检索,显示设备当前可用情况 3. 预约与使用模块 预约管理: 预约规则:学生可预约未来 7 天内的设备 / 实验室,单次最长 4 小时(可设置) 预约流程:选择实验室→选择设备→选择时间段→提交申请(需填写实验目的) 审核机制:普通实验自动通过,高危实验(如化学实验)需教师审核 使用记录: 签到 / 签退:到达实验室后扫码签到,离开时签退,系统自动记录实际使用时长 使用登记:填写实验内容、设备运行情况(正常 / 异常),异常情况需详细描述 违规管理:迟到 15 分钟自动取消预约,多次违规限制预约权限 4. 耗材与安全管理模块 耗材管理: 耗材档案:名称、规格、数量、存放位置、
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值