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

关于objective-c的内存管理,咱们都知道一个原则就是“谁建立,谁释放”,换句话说,不是咱们建立的,就不用咱们去释放。可是实际上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方法 没有被调用,出现了内存泄露。debug

因此最后个人解决办法就是取消那些尚未来得及执行的延时函数,代码很简单:orm

[NSObject cancelPreviousPerformRequestsWithTarget:self]对象

固然你也能够一个一个得这样用:游戏

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

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

 

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

在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: ,不然有可能产生内存泄露,并且这种内存泄露很难发现,由于它并不违反任何规则,因此必定要注意!

相关文章
相关标签/搜索