iOS夯实:ARC时代的内存管理

文章转自 ARC时代的内存管理

什么是ARC

Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory management of Objective-C objects. Rather than having to think about retain and release operations [^1]

[^1]: Transitioning to ARC Release Notes

ARC提供是一个编译器的特性,帮助我们在编译的时候自动插入管理引用计数的代码。
最重要的是我们要认识到ARC的本质仍然是通过引用计数来管理内存。因此有时候如果我们操作不当,仍然会有内存泄露的危险。下面就总结一下ARC时代可能出现内存泄露的场景。

内存泄露类型

  1. 循环引用

    基于引用计数的内存管理机制无法绕过的一个问题便是循环引用(retain cycle)
    (Python同样也采用了基于引用计数的内存管理,但是它采用了另外的机制来清除引用循环导致的内存泄露,而OC和Swift需要我们自己来处理这样的问题[^2])

    • 对象之间的循环引用:使用弱引用避免
    • block与对象之间的循环引用:

    会导致Block与对象之间的循环引用的情况有:

    self.myBlock = ^{ self.someProperty = XXX; };  

    对于这种Block与Self直接循环引用的情况,编译器会给出提示。

    但是对于有多个对象参与的情况,编译器便无能为力了,因此涉及到block内使用到self的情况,我们需要非常谨慎。(推荐涉及到self的情况,如果自己不是非常清楚对象引用关系,统一使用解决方法处理)

    someObject.someBlock = ^{ self.someProperty = XXX; }; //还没有循环引用
    self.someObjectWithABlock = someObject; // 导致循环引用,且编译器不会提醒

    解决方案:

    __weak SomeObjectClass *weakSelf = self;
    
    SomeBlockType someBlock = ^{
    SomeObjectClass *strongSelf = weakSelf;
    if (strongSelf == nil) {
    // The original self doesn't exist anymore.
    // Ignore, notify or otherwise handle this case.
    }
    [strongSelf someMethod];
    };

    我们还有一种更简便的方法来进行处理,实际原理与上面是一样的,但简化后的指令更易用。

    @weakify(self)
    [self.context performBlock:^{
    // Analog to strongSelf in previous code snippet.
    @strongify(self) // You can just reference self as you normally would. Hurray.
    NSError *error;
    [self.context save:&error]; // Do something
    }];

    你可以在这里找到@weakify,@strongify工具:MyTools_iOS

[^2]: How does Python deal with retain cycles?

    1. NSTimer

      一般情况下在action/target模式里 target一般都是被weak引用,除了NSTimer。

      + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)seconds
      target:(id)target
      selector:(SEL)aSelector
      userInfo:(id)userInfo
      repeats:(BOOL)repeats

      在官方文档中:

      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 Programming Topics :

      A timer maintains a strong reference to its target. This means that as long as a timer remains valid, its target will not be deallocated. As a corollary, this means that it does not make sense for a timer’s target to try to invalidate the timer in its dealloc method—the dealloc method will not be invoked as long as the timer is valid.

      举一个例子,一个Timer的Target是ViewController.

      这个时候,如果我们是在dealloc方法里让timer invalidate,就会造成内存泄露.

      事实上,timer是永远不会被invalidate.因为此时VC的引用计数永远不会为零。因为Timer强引用了VC。而因为VC的引用计数不为零,dealloc永远也不会被执行,所以Timer永远持有了VC.

      因此我们需要注意在什么地方invalidate计时器,我们可以在viewWillDisappear里面做这样的工作。

iOS夯实:ARC时代的内存管理的更多相关文章

  1. 【转】iOS夯实:ARC时代的内存管理

    iOS夯实:ARC时代的内存管理 什么是ARC Automatic Reference Counting (ARC) is a compiler feature that provides autom ...

  2. ARC时代的内存管理

    什么是ARC Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory manag ...

  3. iOS经典面试题总结--内存管理

    iOS经典面试题总结--内存管理 内存管理 1.什么是ARC? ARC是automatic reference counting自动引用计数,在程序编译时自动加入retain/release.在对象被 ...

  4. ARC下的内存管理

    1.ARC下单对象内存管理 局部变量释放对象随之被释放 int main(int argc, const char * argv[]) { @autoreleasepool { Person *p = ...

  5. iOS学习17之OC内存管理

    1.内存管理的方式 1> iOS应用程序出现Crash(闪退),90%的原因是因为内存问题. 2> 内存问题 野指针异常:访问没有所有权的内存,如果想要安全的访问,必须确保空间还在 内存泄 ...

  6. iOS学习之Object-C语言内存管理

    一.内存管理的方式      1.iOS应用程序出现Crash(闪退),90%的原因是因为内存问题.      2.内存问题:      1)野指针异常:访问没有所有权的内存,如果想要安全的访问,必须 ...

  7. objective-c启用ARC时的内存管理 (循环引用)

    PDF版下载:http://download.csdn.net/detail/cuibo1123/7443125          在Objective-C中,内存的引用计数一直是一个让人比较头疼的问 ...

  8. iOS之Block总结以及内存管理

    block定义 struct Block_descriptor { unsigned long int reserved; unsigned long int size; void (*copy)(v ...

  9. objective-c启用ARC时的内存管理

    PDF版下载:http://download.csdn.net/detail/cuibo1123/7443125      在objective-c中,内存的引用计数一直是一个让人比較头疼的问题.尤其 ...

随机推荐

  1. 第二十章、启动流程、模块管理与 Loader

    核心与核心模块 在整个启动的过程当中,是否能够成功地驱动我们主机的硬件配备, 是核心 (kernel) 的工作!而核心一般都是压缩档,因此在使用核心之前,就得要将它解压缩后, 才能加载主内存当中. 另 ...

  2. uCos 没有延时Tick滴答定时器测试

    原来学uCos只是表面,今天才发现uCos没有心跳也是可以活的,只是延时功能. 即:OSTimeDly.OSTimexxx 头的功能不能使用. 如果有是用OSTimexxx,任务将会卡死.其实,OST ...

  3. .NET自带IOC容器MEF之初体验

    .NET自带IOC容器MEF之初体验   本文主要把MEF作为一种IOC容器进行讲解,.net中可用的IOC容器非常多,如 CastleWindsor,Unity,Autofac,ObjectBuil ...

  4. PowerDesigner 物理数据模型(PDM)

    PowerDesigner 物理数据模型(PDM) 说明 数据库脚本sqldatabasegeneration存储   目录(?)[+]   一.     PDM 介绍 物理数据模型(Physical ...

  5. Python Telnet弱口令爆破脚本及遇到的错误与问题

    写得时候遇到了一个很大的问题,就是我在发送用户名,接受用户名就会一直卡住.然后等了好久后提示 recv ‘\r\nSession timed out.\r\n\r\nTelnet Server has ...

  6. PowerShell查询sql server

    function Invoke-SQL1: function Invoke-SQL { param( [string] $DBServer, [string] $Database, [string] ...

  7. DHCP Option 60 的理解

    原文地址: http://blog.163.com/chenqioulin_1983/blog/static/83216232010109104430251/   首先还是看看RFC咋说的吧.DHCP ...

  8. 【M12】了解“抛出一个exception”与“传递一个参数”或“调用一个虚函数”之间的差异

    1.方法参数的声明语法和catch语句的语法是一样的,你可能会认为主调方法调用一个方法,并向其传递参数,与抛出一个异常传递到catch语句是一样的,是的,有相同之处,但也有更大的不同. 2.主调方法调 ...

  9. [AngularJS] Taking control of your templates using $templateCache

    Using $templateCache for quickly retrieval from the cache after first time used. $templateCache main ...

  10. 小谈一下Java I/O

    java中的I/O操作宏观上来说就氛围两个种类,一个是字节流 ,一个是字符流,分别相应着一组类和接口 字节流: InputStream 输入流的基类 OutputStream 输出流的基类 对于字节流 ...