ARC内存优化

ARC虽然是自动引用计数,但我们在进行ARC开发的时候也需要注意一些问题如一下四点:

一.ARC下需要注意:

1.在ARC下使用音频播放器来播放音乐的时候,要注意要将AVAudioPlayer声明成属性,来提高播放器的声明周期,要不然是不会进行音乐播放的

//  *1.在ARC播放音频文件的时候,记得提高音频播放器的生命周期

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"小苹果" ofType:@"mp3"];

NSURL *fileURL = [NSURL fileURLWithPath:filePath];

self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];

[_audioPlayer play];

2.

在使用KVO的时候,我们要把观察者声明成属性,要不然会系统崩溃,访问一块坏的内存,因为观察者要持续观察被观察者属性的变化,而ARC是编译器自己在

适合的地方为我们加上release进行内存管理,观察者对象的释放不由我们控制,我们仍然要把观察者声明成属性,来提高观察者对象的声明周期,让观察者

对象不能提前释放

//  *2.KVO使用的时候

self.secVC = [[SecondViewController alloc] init];

[self addObserver:_secVC forKeyPath:@"lanouNumber" options:NSKeyValueObservingOptionNew context:NULL];

3.ARC下也需要注意内存的循环引用问题,循环引用就是两个对象相互引用,导致两个对象的内存都没有办法释放,从而引起内存泄露

//  3.循环引用现象

//  teacher:1

Teacher *teacher = [[Teacher alloc] init];

//  student:1

Student *student = [[Student alloc] init];

//  student:2

teacher.stu = student;

//  teacher:2

student.tea = teacher;

//  解决arc下循环引用问题:

//  弱化其中任何一个强引用属性,打破强引用链,在当前的例子中就是在Teacher类中将student的属性变化weak

//  weak,也可以使用assign

//  weak修饰对象类型,不能修饰基础类型,assign可以修饰对象类型,也可以修饰基础类型,区别:weak修饰的属性在dealloc之后,会进行安全处理,将该属性自动赋值为nil

4.arc下block的循环引用及解决方案

//  4.arc下block的循环引用

//  arc下出现block的循环引用,解决方案:在block中使用__weak修饰的变量

Teacher *tea = [[Teacher alloc] init];

Teacher *teacher = tea;

//  下面的使用方式,就会出现循环引用现象

[tea setMyBlock:^{

NSLog(@"%@", teacher);

}];

解决方法:

在变量将要被引入到block块中之前,在ARC下添加__weak关键字,MRC下使用__block关键字

__weak Teacher *teacher = tea;

二. 程序受到内存警告之后的处理

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

//  1.用来判断当前控制器的视图有没有被加载过

//  2.我们可以通过这个属性来判断当前这个view有没有在window上显示

if (self.isViewLoaded && !self.view.window) {

//  1.我们可以把一些强引用属性赋值为nil

//  2.我们可以把当前控制器的view置为nil,用来节省内存,我们再次切换到这个控制器的时候,系统会自动再次触发loadView方法帮助我们创建view

//  释放声明的强引用属性

self.lanouNumber = nil;

self.audioPlayer = nil;

self.secVC = nil;

//  将控制器的view置为nil,因为控制器的view没有在window上显示,节省资源

self.view = nil;

NSLog(@"rootView dead");

}

}

三.ARC下autoreleasepool的使用

ARC

下使用NSThread创建的子线程,在子线程中执行的方法中,系统并没有为我们创建自动释放池,所以一些autorelease的属性不能及时释放,当

我们写到了release/retain等方法, ARC 下你不能写这些方法,但ARC

会帮你在合适的地方插入这些方法。这将导致内存的延迟释放。autoreleasepool是为了 autorelease

这个方法,在对象的创建者没法销毁对象的时候,可以使用autorelease让autoreleasepool每隔一段时间检查该对象的引用计数,如果

为0则释放对象。那么多个autoreleasepool的作用就是增加这种间隔,比原本autorelease释放的时间更早释放。

所以无论在ARC还是MRC我们使用NSThread的时候,方法中需要加入自动释放池

//  NSThread

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadAction:) object:nil];

//  手动开启

[thread start];

//  就是在子线程中去执行的方法

- (void)threadAction:(NSThread *)sender

{

//  我们无论在ARC下还是MRC,在NSThread方法中都需要我们把新增的对象类型放到autoreleasepool。

//  *因为NSThread开辟子线程中并没有自动释放池,没有办法对autorelease修饰的类型进行释放

@autoreleasepool {

NSLog(@"-----%d", [NSThread isMainThread]);

Teacher *teacher = [[Teacher alloc] init];

}

}

你可能感兴趣的:(ARC内存优化)