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