内存优化的实质是,在手机内存有限的情况下,最大限度的保证程序运行流畅和尽可能的优化使用, 首先明确,程序运行状态的优先级分别为: 勉强运行 > 卡顿 > 高负荷运转 > 正常运转
程序要先保证能运行,然后再谈良好运转. 所以解决问题比较宽泛,必要的时候在交互或者运转机制上小动刀子来保证既能完成任务,程序又能正常运转.
毕竟在优化效率达到上限的时候,只能用时间换空间了
主要分为三点:
- 减少内存泄露
- 降低内存使用峰值
- 减少内存异常引用
可怕的内存泄露
内存泄露的实质是, 堆区的内存被分配之后,没有在使用完成之后,在适当的时候被释放掉.比如下面代码:
- (void)dealloc {
NSLog(@"释放了");
}
- (void)request {
[YCNetShareManager loginWithUsername:userName password:password success:^(id responseObject) {
self.res = responseObject;
} failure:^(NSString *errorMsg) {
}];
}
success block会持有其函数内所有的变量, 比如self.
可怕的点在于,由于arc下强持有的变量无法被释放,而request方法为对象方法,也就是其被self所持有, 所以引用的过程也就是: self -> request方法 -> success block -> self
形成了一个强引用的持有链条,当退出页面后,dealloc方法不会被调用.这一组内存就被占用了,所以有些App如果做的很差,用户就会发现自己越用越卡,经常内存溢出甚至导致设备重启,罪魁祸首就是内存泄露过多,当App占用过高的内存,直接被系统kill,亦称闪退
万幸的是,我在做自己写demo做实验的时候发现, 同一段代码即便内存泄露,反复调用也不会占用多份内存,系统会在第二段内存申请的时候, 释放第一份内存.
weak strong dance
要解决循环引用的问题,就要用到weak strong dance
核心改造一下引用链条将其变成: self -> request方法 -> success block -> weakself -> self
这样让block持有的是弱引用的self,这样就不会因为,有强引用循环链,造成内存泄露了.例如:
- (void)dealloc {
NSLog(@"释放了");
}
- (void)request {
__weak typeof(self)weakSelf = self;
[YCNetShareManager loginWithUsername:userName password:password success:^(id responseObject) {
__weak typeof(weakSelf) strongSelf = weakSelf;
strongSelf.res = responseObject;
} failure:^(NSString *errorMsg) {
}];
}
如果block中只使用weakSelf,其也是可以成立的,但是可能出现,当网络请求还没有完成的时候, 页面已经退出,整体被释放.当请求响应的时候,其已经释放,尽管weak类型的变量已经置空变为nil,但依然有可能引起崩溃, 所以这个时候要解决这个问题就需要
__weak typeof(weakSelf) strongSelf = weakSelf;
其可以保证在success block调用完毕之后再释放内存
降低内存使用峰值
在一些使用场景里,比如整个页面初始化,要分配整个使用内存,批量的图片处理,会出现段时间需要加载大量内容,占用过高的内存.
这个时候单纯的降低内存使用是行不通的法则,只能用时间换空间,拉长整个加载步骤:
- lazy load, 懒加载
- 灵活运用图片和文件加载
- 拉长文件处理机制,逐步处理文件
网友评论