来源:http://hi.baidu.com/douxinchun/item/920a7655fe7f3fd8d48bacaf

最近在使用NSTimer的时候,遇到了一些内存错误的问题,找了一片很好的文章可惜是英文的,现自己翻译出来,以备后用。

原文:

[timer release] only needs to be called if you “own” the timer. From Apple’s documentation:

Because the run loop maintains the timer, from the perspective of memory management there’s typically no need to keep a reference to a timer once you’ve scheduled it. Since the timer is passed as an argument when you specify its method as a selector, you can invalidate a repeating timer when appropriate within that method. In many situations, however, you also want the option of invalidating the timer—perhaps even before it starts. In this case, you do need to keep a reference to the timer, so that you can send it an invalidate message whenever is appropriate. If you create an unscheduled timer (see “Unscheduled Timers”), then you must maintain a strong reference to the timer (in a reference-counted environment, you retain it) so that it is not deallocated before you use it.

What does this mean?

If you alloc and init a timer, you must also release it, like so:

NSTimer * timer = [[NSTimer alloc] initWith…];

NSRunLoop * runLoop = [NSRunLoop currentRunLoop];

[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];

[timer release];

……

[timer invalidate];

timer = nil;

Once the timer has been added to the run loop, there is no reason to keep a reference to it anymore, since the run loops owns it. In this case, as shown, you would release the timer as soon as you add it to the run loop, and then simplyinvalidate it when you are finished. The final line (setting timer to nil) is for safety. The call to invalidate will result in the timer being released (by the run loop), so it is unsafe to keep a reference that points to it. Setting the local reference to nil keeps things kosher.

If, however, you create a timer using one of the convenience methods like so:

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

You do not need to call [timer release] at all!

The convenience method adds the timer to the run loop, which then owns it, so you do not need to perform any memory management on the returned timer object. You would simplyinvalidate the timer when you no longer want to use it:

[timer invalidate];timer = nil;

Or, if the timer was not set to repeat, you would do absolutely nothing at all, since it would be released after its first invocation.

译文:[timer release]这个方法只有在当你拥有timer的时候才可以调用。根据Apple的文档描述如下:由于RunLoop保持着timer。从内存管理的角度上看,当我们scheduled(预定)一个timer的时候,我们通常是不需要保持它的reference(引用计数)的。由于timer是作为一个参数传递的,timer的指定的方法是selector的形式,所以你可以在指定的方法的内部,在合适的时候invalidate一个重复的timer(repeating timer)。然而,在许多的场合下,你可能会想在timer开始之前就invalidating timer。在这种情况下,又必须保持一个对timer的引用(reference),以便于你可以合适的时间向timer发送invalidate消息。如果你创建了一个 unscheduled timer,你必须保持一个对于这个timer的 strong reference(在 reference_count(引用计数的环境下),你给timer发送了一个retain的消息),n这样做目的是保证在你使用该timer之前,它不会被deallocated。简言之:如果你allloc init了一个timer,你必须release it,例如:

NSTimer * timer = [[NSTimer alloc] initWith…];

NSRunLoop * runLoop = [NSRunLoop currentRunLoop];

[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];

[timer release];

……

[timer invalidate];

timer = nil;

一旦timer被加入了Runloop,我们就没有任何原因来保持一个引用,因为Runloop会保持它。在这个展示中,正如我们我展示的,你应该release 掉它,当你把它添加进Runloop的时候,并且像示例中的那样在timer结束的时候 invalidate 。最后一行代码(timer = nil)是为了安全。invalidate 的调用会使得timer被release(由Runloop控制),所以保持一个指向timer的引用是不安全。将本地的引用设置为空是符合规则的。

无论如何,如果你创建一个timer按照下面的这种形式:

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

你根本不需要 调用 [timer release]!

这个便捷的方法,把timer加入到了Runloop,Runloop会保持timer的引用计数,所以你不需要在返回的timer对象上实现任何的

内存管理。你应该想示例的那样invalidate timer,如下:

[timer invalidate];timer = nil;

或者,如果timer没有设置重复(repeat),你就安心的不需要做任何的事情,因为他会在第一次调用完成后release timer。

iphone NSTimer invalidate 和 release 释放问题的更多相关文章

  1. 使用NSTimer实现动画

    1.新建empty AppLication,添加HomeViewController页面, iphone.png图片 2.在 HomeViewController.xib中添加Image View,并 ...

  2. iphone开发第二个程序

    此程序包括UIProgressView,UIButton, UIDatePicker,UIAlert,UILabel,NSTimer // //  HViewController.h //  Btn_ ...

  3. 页面实现多个定时器(计时器)时选用NSTimer还是GCD?(干货不湿)

    定时器在我们每个人做的iOS项目里面必不可少,如登录页面倒计时.支付期限倒计时等等,一般来说使用NSTimer创建定时器: + (NSTimer *)timerWithTimeInterval:(NS ...

  4. NSTimer深入理解

    NSTimer,即计时器,用于定时执行一些任务,一次或者多次. 系统Foundation框架提供的最常用方法如下,创建一个NSTimer,并将它放到当前runloop的default mode中. + ...

  5. NSTimer内存泄漏

    用NSTimer调用 timer = [NSTimer scheduledTimerWithTimeInterval:timerInterval target:self selector:@selec ...

  6. NSTimer使用注意事项

    1.scheduled开头和非schedule的开头方法的区别.系统框架提供了几种创建NSTimer的方法,其中以scheduled开头的方法会自动把timer加入当前run loop,到了设定的时间 ...

  7. GCD实现多个定时器,完美避过NSTimer的三大缺陷(RunLoop、Thread、Leaks)

    定时器在我们每个人做的iOS项目里面必不可少,如登录页面倒计时.支付期限倒计时等等,一般来说使用NSTimer创建定时器: + (NSTimer *)timerWithTimeInterval:(NS ...

  8. Xcode证书破解 iphone真机部署

    Xcode证书破解 iphone真机部署 证书伪造: 先按照该教程的步骤添加证书.注意,原教程选择的是"系统"证书,这里我们用"登录"证书,切记. Xcode破 ...

  9. 2.从AbstractQueuedSynchronizer(AQS)说起(1)——独占模式的锁获取与释放

    首先我们从java.util.concurrent.locks包中的AbstraceQueuedSynchronizer说起,在下文中称为AQS. AQS是一个用于构建锁和同步器的框架.例如在并发包中 ...

随机推荐

  1. Android A/B System OTA分析(一)概览【转】

    本文转载自:https://blog.csdn.net/guyongqiangx/article/details/71334889 Android从7.0开始引入新的OTA升级方式,A/B Syste ...

  2. java 465端口发送邮件

    package com.fr.function; import java.io.IOException; import java.security.Security; import java.util ...

  3. 转 perl DBI 总结

    https://www.cnblogs.com/homezzm/archive/2011/07/22/2113618.html ##查看已经安装的包 #!/usr/bin/perluse strict ...

  4. [LeetCode] 460. LFU Cache 最近最不常用页面置换缓存器

    Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the f ...

  5. Kubernetes Pod应用的滚动更新(八)

    一.环境准备 我们紧接上一节的环境,进行下面的操作,如果不清楚的,可以先查看上一篇博文. 滚动更新是一次只更新一小部分副本,成功后,再更新更多的副本,最终完成所有副本的更新.滚动更新的最大的好处是零停 ...

  6. 【计算机视觉】PASCAL VOC数据集分析

    PASCAL VOC数据集分析 PASCAL VOC为图像识别和分类提供了一整套标准化的优秀的数据集,从2005年到2012年每年都会举行一场图像识别challenge. 本文主要分析PASCAL V ...

  7. SpringBoot系列教程JPA之delete使用姿势详解

    原文: 190702-SpringBoot系列教程JPA之delete使用姿势详解 常见db中的四个操作curd,前面的几篇博文分别介绍了insert,update,接下来我们看下delete的使用姿 ...

  8. swoole实现多人游戏的要点

    swoole实现多人游戏的要点 比方说多人在线 要满足以下两点 1 所有玩家的数据要实时更新到服务器数据库数据 2 写个定时器返回数据

  9. 02_四大组件之Activity

    四大组件之Activity 1. 理论概述 1.1 Activity的理解 Servlet的理解回顾 狭义 Servlet是一个interface,我们的Servlet类都必须是此接口的实现类 广义 ...

  10. 一起来学Spring Cloud | 第八章:消息总线(Spring Cloud Bus)

    上一章节,我们讲解了分布式配置中心spring cloud config,我们把配置项存放在git或者本地,当我们修改配置时,需要重新启动服务才能生效.但是在生产上,一个服务部署了多台机器,重新启动比 ...