美文网首页
iOS中结合代码看内存管理(一)

iOS中结合代码看内存管理(一)

作者: Nlinger | 来源:发表于2017-06-07 15:51 被阅读81次

阅读本文前,建议移步先去了解下内存管理相关知识。

1: iOS内存管理机制(百度goole大法可以获得很多推荐)。

2: iOS中的动态内存分配

3: 堆栈的原理:堆栈 百科

1:自动释放池的常见问题:

较大的循环时如果不及时释放,可能会导致内存暴涨。

for (int i = 0; i < 100000; i ++) {

@autoreleasepool {  //解决方案:逐条释放,避免暴涨

NSString * log  = [NSString stringWithFormat:@"%d", i];

NSLog(@"%@", log); }

}

2: 修饰符的常见问题:

ARC提供四种修饰符,分别是strong, weak, autoreleasing, unsafe_unretained

__strong:强引用,持有所指向对象的所有权,无修饰符情况下的默认值。如需强制释放,可置nil。

比如我们常用的定时器:

NSTimer * timer = [NSTimer timerWith...];

相当于

NSTimer * __strong timer = [NSTimer timerWith...];

当不需要使用时,强制销毁定时器

[timer invalidate];

timer = nil;

__weak:弱引用,不持有所指向对象的所有权,引用指向的对象内存被回收之后,引用本身会置nil,避免野指针。

比如避免循环引用的弱引用声明:

__weak __typeof(self) weakSelf = self;

ps: 诸如网络请求的时候避免弱指针丢掉,往往需要在block内部从新strong下该指针。

__strong __typeof(weakSelf) strongSelf = weakSelf;

__autoreleasing:自动释放对象的引用,一般用于传递参数

比如一个读取数据的方法

- (void)loadData:(NSError **)error;

当你调用时会发现这样的提示

NSError * error;

[dataTool loadData:(NSError *__autoreleasing *)]

这是编译器自动帮我们插入以下代码

NSError * error;

NSError * __autoreleasing tmpErr = error;

[dataTool loadData:&tmpErr];

__unsafe_unretained:为兼容iOS5以下版本的产物,可以理解成MRC下的weak,现在基本用不到,这里不作描述。

3.  属性的内存管理

ObjC2.0引入了@property,提供成员变量访问方法、权限、环境、内存管理类型的声明,下面主要说明ARC中属性的内存管理。

属性的参数分为三类,基本数据类型默认为(atomic,readwrite,assign),对象类型默认为(atomic,readwrite,strong),其中第三个参数就是该属性的内存管理方式修饰,修饰词可以是以下之一:

1)assign:直接赋值

assign一般用来修饰基本数据类型

@property (nonatomic, assign) NSInteger count;

当然也可以修饰ObjC对象,但是不推荐,因为被assign修饰的对象释放后,指针还是指向释放前的内存,在后续操作中可能会导致内存问题引发崩溃。(!!!!!bug预警)

2)retain:release旧值,再retain新值(引用计数+1)

retain和strong一样,都用来修饰ObjC对象。

使用set方法赋值时,实质上是会先保留新值,再释放旧值,再设置新值,避免新旧值一样时导致对象被释放的的问题。

MRC写法如下

- (void)setCount:(NSObject *)count {

[count retain];

[_count release];

_count = count;

}

ARC对应写法

- (void)setCount:(NSObject *)count {

_count = count;

}

3)copy:release旧值,再copy新值(拷贝内容)

一般用来修饰String、Dict、Array等需要保护其封装性的对象,尤其是在其内容可变的情况下,因此会拷贝(深拷贝)一份内容給属性使用,避免可能造成的对源内容进行改动。

使用set方法赋值时,实质上是会先拷贝新值,再释放旧值,再设置新值。

实际上,遵守NSCopying的对象都可以使用copy,当然,如果你确定是要共用同一份可变内容,你也可以使用strong或retain。

@property (nonatomic, copy) NSString * name;

4)weak:ARC新引入修饰词,可代替assign,比assign多增加一个特性(置nil,见上文)。  weak和strong一样用来修饰ObjC对象。

使用set方法赋值时,实质上不保留新值,也不释放旧值,只设置新值。

比如常用的代理的声明    

 @property (weak) id delegate;

Xib控件的引用

@property (weak, nonatomic) IBOutlet UIImageView *productImage;

5)strong:ARC新引入修饰词,可代替retain

可参照retain,这里不再作描述。

4. block的内存管理

iOS中使用block必须自己管理内存,错误的内存管理将导致循环引用等内存泄漏问题,这里主要说明在ARC下block声明和使用的时候需要注意的两点:

1)如果你使用@property去声明一个block的时候,一般使用copy来进行修饰(当然也可以不写,编译器自动进行copy操作),尽量不要使用retain。

@property (nonatomic, copy) void(^block)(NSData * data);

2)block会对内部使用的对象进行强引用,因此在使用的时候应该确定不会引起循环引用,当然保险的做法就是添加弱引用标记。

__weak typeof(self) weakSelf = self;

相关文章

  • iOS中结合代码看内存管理(一)

    阅读本文前,建议移步先去了解下内存管理相关知识。 1: iOS内存管理机制(百度goole大法可以获得很多推荐)。...

  • RxSwift-内存管理

    在iOS中采用的引用计数来管理内存,ARC中,编译阶段,系统会自动向代码中插入内存管理代码,无非就是对对象的引用做...

  • iOS 内存管理 部分三

    主要讲解日常开发中定时器的选择; iOS 内存管理 部分一iOS 内存管理 部分二iOS 内存管理 部分三i...

  • OC中内存管理

    在OC中内存管理MRC手动内存管理和ARC自动内存管理,ARC是从iOS 4.0开始,在iOS 4.0之前...

  • iOS之从MRC到ARC内存管理详解

    概述 在iOS中开发中,我们或多或少都听说过内存管理。iOS的内存管理一般指的是OC对象的内存管理,因为OC对象分...

  • iOS/OS X内存管理(二):借助工具解决内存问题

    上一篇博客iOS/OS X内存管理(一):基本概念与原理主要讲了iOS/OSX 内存管理中引用计数和内存管理规则,...

  • iOS 内存简单介绍

    iOS内存管理 iOS内存分为5个区:栈区,堆区,全局区,常量区,代码区 栈区stack:这一块区域系统会自己管理...

  • ios内存管理

    ios内存管理 一.前言 在ios中,系统对每个程序运行时内存的占有...

  • 2019-11-14 记iOS高级工程师面试题

    1. 简述一下iOS的内存管理? 内存条中主要分为几大类:栈区(stack)、堆区(heap)、常量区、代码区(....

  • iOS内功篇:内存管理

    iOS内功篇:内存管理 iOS内功篇:内存管理

网友评论

      本文标题:iOS中结合代码看内存管理(一)

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