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

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

若是场景切换的时候dealloc没有调用,说明你这个场景的内存有问题。有可能被某个对象retain了,其retainCount在 replaceScene的时候没有减小到0,因此dealloc方法是不会调用的。若是dealloc方法都没有调掉,那么这其实就是一种内存泄露。函数

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

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

[NSObject cancelPreviousPerformRequestsWithTarget:self]游戏

固然你也能够一个一个得这样用:内存

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

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

 

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

在touchBegan里面io

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

相关文章
相关标签/搜索