美文网首页
ios内存管理-ARC

ios内存管理-ARC

作者: Gomu_iOS | 来源:发表于2018-08-30 10:56 被阅读0次

    一、概要

     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

    相关文章

      网友评论

          本文标题:ios内存管理-ARC

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