performSelector延时调用导致的内存泄露

news/2024/7/20 15:20:32 标签: 内存管理, 移动开发

前几天在给游戏做收尾测试时,发现了一个关于内存泄露的问题,一直没找着问题所在,经过反复调试和查找资料今天终于解决了,特此记录下来以免以后再犯!

关于objective-c的内存管理,我们都知道一个原则就是“谁创建,谁释放”,换句话说,不是我们创建的,就不用我们去释放。但是实际上objective-c的内存管理远远没那么简单,我的情况是这样的:

我在debug模式下面用CCLOG在dealloc函数里面输出一些信息,目的就是要检查场景的dealloc方法在replaceScene的时候有没有被调用,按照子龙山人大哥的说法,如果场景切换的时候dealloc没有调用,说明你这个场景的内存有问题。有可能被某个对象retain了,其retainCount在replaceScene的时候没有减少到0,所以dealloc方法是不会调用的。如果dealloc方法都没有调掉,那么这其实就是一种内存泄露。我在检查时,发现一个场景死活不调用dealloc,最后恨不得把所有的游戏逻辑都移除了,还是不走dealloc。

最后的最后才发现实际上是performSelector延时调用的问题,经查找资料,performSelector关于内存管理的执行原理是这样的执行 [self performSelector:@selector(method1:) withObject:self.tableLayer afterDelay:3]; 的时候,系统会将tableLayer的引用计数加1,执行完这个方法时,还会将tableLayer的引用计数减1,而在我的游戏里这个延时执行函数是被多次调用的,有时切换场景时延时函数已经被调用但还没有执行,这时tableLayer的引用计数没有减少到0,也就导致了切换场景dealloc方法没有被调用,出现了内存泄露。

所以最后我的解决办法就是取消那些还没有来得及执行的延时函数,代码很简单:

[NSObject cancelPreviousPerformRequestsWithTarget:self]

当然你也可以一个一个得这样用:

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(method1:) object:nil]

加上了这个以后,切换场景也就很顺利地执行了dealloc方法,至此问题解决!

最后在找资料时也发现了,延时调用实现长按钮的实现思路,记录下来以备后用:

在touchBegan里面

[self performSelector:@selector(longPressMethod:) withObject:nil afterDelay:longPressTime]

然后在end 或cancel里做判断,如果时间不够长按的时间调用:

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(longPressMethod:) object:nil]

取消began里的方法

最后最后总结:

performSelector是一个很有用的函数,跟它打过不少交道,经过血与泪的教训,总结一下它的使用如下:

使用前先检测一下,

SEL testSelector = @selector(test:);

if([tester respondsToSelector:testSelector])

{

//如果响应就执行

[tester test:@"invoke test method"];

}

使用后,如果有必要,需要显示的调用cancelPreviousPerformRequestsWithTarget:selector:object: ,否则有可能产生内存泄露,而且这种内存泄露很难发现,因为它并不违反任何规则,所以一定要注意!


http://www.niftyadmin.cn/n/1751704.html

相关文章

Java高级部分笔记-------类加载器

2019独角兽企业重金招聘Python工程师标准>>> 1.类加载器的概念及其作用 顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序&…

[转]异步编程与响应式框架

作者:老赵 来源:http://blog.zhaojie.me/2010/09/async-programming-and-reactive-framework.html 前言 异步操作是强大的,它是许多高伸缩性架构的基石。异步操作在许多情况下是必须的,例如在客户端保持用户界面的响应能力&#…

php协程 关键字,php +go关键字实现协程 | 码农网

今天在知乎浏览时忽然发现了一个有趣的东西,php竟然可以实现协程的实现,而且还是通过 go 关键字实现,顿时感觉 php 现在发展的好迅速,竟然把go里的东西都借鉴去。只不过这是在一个叫Swoole的框架中实现的。Swoole4为 PHP 语言提供…

Eclipse:Could not create the view: Plug-in org.eclipse.jdt.ui was unable to load class org.eclipse.

使用Eclipse时,遇到了如下的异常,工作空间(workspace)打不开:Could not create the view: Plug-in org .eclipse. jdt.ui was unable to load class org .eclipse. jdt.internal.ui.packageview.PackageExplorerPart.*…

centos配置ruby开发环境

2019独角兽企业重金招聘Python工程师标准>>> centos配置ruby开发环境1. 安装ruby 1.1 yum安装,版本旧 #yum install ruby ruby-devel ruby-ri ruby-rdoc ruby-irb ruby-shadow 1.2 删除 #yum remove ruby ruby-devel -y 1.3 源码安装 #wget http://cache…

c odbc连接mysql,请问在C语言中,怎么利用ODBC连接数据库

当前位置:我的异常网 C语言 请问在C语言中,怎么利用ODBC连接数据库请问在C语言中,怎么利用ODBC连接数据库www.myexceptions.net 网友分享于:2013-03-08 浏览:13次请教在C语言中,如何利用ODBC连接数据库?…

PopupWindow中使用GridView无法响应OnItemClickListener点击事件

在PopupWindow中使用GridView&#xff0c;但是GridView中的各个item点击无法响应事件&#xff0c;这是需要添加<wbr style"color:rgb(70,70,70); font-family:simsun; font-size:14px; line-height:21px; text-align:left"><span style"color:rgb(70,7…

锁屏软件项目可行性研究报告

1引言 1 1.1编写目的 1 1.2背景 1 1.3定义 1 1.4参考资料 1 2可行性研究的前提 2 2.1要求 2 2.2目标 2 2.3条件、假定和限制 3 2.4进行可行性研究的方法 3 2.5评价尺度 3 3对现有系统的分析 3 3.1处理流程和数据流程 4 3.2工作负荷 4 3.3费用开支 4 3.4人员 4 3.5设备 4 3.6局限…