ios内存管理-ARC

2018-08-30  本文已影响0人  Gomu_iOS

一、概要

 iOS5后出现了ARC。那么ARC是什么呢?自动引用计数ARC是一种编译器的功能,为Objective-C对象提供了自动化的内存管理。在ARC不需要开发者考虑保留或者释放的操作,就是不用自己手动retain、release和autorelease。 当然ARC依然是基于引用计数管理内存。

二、ARC 强制新规则

ARC相对于MRC强制加了一些新的规则。

1、你不能主动调用dealloc、或者调用retain,release,retainCount,autorelease就是这些都不用你写了。也不能@selector(retain),@selector(release)这样子调用。

2、你可以实现一个dealloc方法,如果你需要管理资源而不是释放实例变量(比如解除监听、释放引用、socket close等等)。在重写dealloc后需要[super dealloc](在手动管理引用计数时才需要)。

3、仍然可以使用CFRetain,CFRelease等其它对象。

4、你不能使用NSAllocateObject或者NSDeallocateObject。

5、你不能使用C结构体,可以创建一个Objective-C类去管理数据而不是一个结构体。

6、id和void没有转换关系,你必须使用cast特殊方式,以便在作为函数参数传递的Objective-C对象和Core Foundation类型之间进行转换。

7、你不能使用NSAutoreleasePool,使用@autoreleasepool。

8、没必要使用NSZone。

三、ARC 使用新修饰符 

1、__strong 强引用,用来保证对象不会被释放。

2、 __weak弱引用 释放时会置为nil 

3、 __unsafe_unretained弱引用 可能不安全,因为释放时不置为nil。 

4、__autoreleasing对象被注册到autorelease pool中方法在返回时自动释放。

四、内存泄漏

ARC还是基于引用计数的管理机制所以依然会出现循环引用。

五、block使用中出现循环引用

1、常见的有情况在block使用中出现循环引用

// 情况一

self.myBlock = ^{self.objc = ...;};

// 情况二

Dog *dog = [[Dog alloc] init];

dog.myBlock = ^{ // do something};

self.dog = dog;

解决方法

__weak typeof (self) weakSelf = self;

self.myBlock = ^{weakSelf.objc = ...;};

2、那么如果block内使用了self这个时候如果某一个时刻self被释放就会导致出现问题。

解决办法

__weaktypeof(self) weakSelf =self;

self.myBlock = ^{

__strongtypeof(self) strongSelf = weakSelf;

strongSelf.objc1 = ...;

strongSelf.objc2 = ...;

strongSelf.objc3 = ...;

};

使用__weak打破循环引用。__strong用来避免在使用self过程中self被释放,__strong在block后会调用objc_release(obj)释放对象。

id__strongobj = [[NSObjectalloc] init];

// clang 编译后

idobj = objc_msgSend(NSObject,@selector(alloc));

objc_msgSend(obj,@selector(init));

objc_release(obj);

两次调用objc_msgSend并在变量作用域结束时调用objc_release释放对象,不会出现循环引用问题。

3、NSTimer循环引用

主要是因为NSRunloop运行循环保持了对NSTimer的强引用,并且NSTimer的targer也使用了强引用。

来自文档NSTimer

Note in particular that run loops maintain strong references to their timers, so you don’t have to maintain your own strong reference to a timer after you have added it to a run loop.

target

The object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to this object until it (the timer) is invalidated.

解决方法:

手动调用[timer invalidate]来解除持有关系,释放内存。可能会想到在dealloc方法中来手动调用,但是因为timer持有控制器,所以控制器的dealloc方法永远不会调用,因为dealloc是在控制器要被释放前调用的。在Timer Programming Topics中有特别说明。所以一般我们可以在下面这些方法中手动调用[timer invalidate]然后置为nil:

- (void)viewWillDisappear:(BOOL)animated;// Called when the view is dismissed, covered or otherwise hidden. Default does nothing

- (void)viewDidDisappear:(BOOL)animated;// Called after the view was dismissed, covered or otherwise hidden. Default does nothing

上一篇下一篇

猜你喜欢

热点阅读