Cocos2d-x游戏开发实例详解7:对象释放时机
在上两篇文章中,我们详细讲解了内存自动释放机制。在本篇文章中,我们将深入探讨自动对象的释放时机。
当一个对象调用 autorelease()
函数后,它会被加入到自动释放池中。那么,这个对象究竟何时会被释放呢?下面我们从游戏主循环开始进行跟进分析。
游戏主循环起始点 CCApplication::run()
以下是 CCApplication::run()
函数的代码:
int CCApplication::run()
{
if (applicationDidFinishLaunching())
{
[[CCDirectorCaller sharedDirectorCaller] startMainLoop]; // 主循环开始
}
return 0;
}
在这个函数中,如果 applicationDidFinishLaunching()
函数返回 true
,则会调用 CCDirectorCaller
单例的 startMainLoop
方法,从而启动游戏的主循环。
跟进 startMainLoop
函数
-(void) startMainLoop
{
// CCDirector::setAnimationInterval() is called, we should invalidate it first
[displayLink invalidate];
displayLink = nil;
// displayLink是CADisplayLink对象,target是自己,回调是coCaller
displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doCaller:)]; // 看这个doCaller回调
[displayLink setFrameInterval: self.interval]; // 设置帧率
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; // 添加到循环并启动
}
在 startMainLoop
函数中,首先会使之前的 displayLink
失效并置为 nil
。然后创建一个新的 CADisplayLink
对象,将其 target
设置为自身,回调方法设置为 doCaller:
。接着设置帧率,并将 displayLink
添加到当前的运行循环中启动。这里我们重点关注 doCaller
回调函数。
doCaller
回调函数 CCDisplayLinkDirector::mainLoop
void CCDisplayLinkDirector::mainLoop(void)
{
if (m_bPurgeDirecotorInNextLoop)
{
m_bPurgeDirecotorInNextLoop = false;
purgeDirector();
}
else if (! m_bInvalid)
{
drawScene(); // draw the scene
// release the objects
CCPoolManager::sharedPoolManager()->pop();
}
}
在 CCDisplayLinkDirector::mainLoop
函数中,首先会检查 m_bPurgeDirecotorInNextLoop
标志。如果该标志为 true
,则将其置为 false
并调用 purgeDirector()
函数。如果该标志为 false
且 m_bInvalid
为 false
,则会调用 drawScene()
函数绘制场景,然后调用 CCPoolManager::sharedPoolManager()->pop()
函数释放对象。
对象释放点
经过上述分析,我们可以看到,在一个循环结束时,CCPoolManager::sharedPoolManager()->pop()
函数被调用,这个函数就是用来释放自动释放池中的对象的。如果有同学对具体的释放过程感兴趣,可以深入跟进该函数的实现。
通过以上对游戏主循环的逐步分析,我们清晰地了解了自动对象在 Cocos2d-x 中的释放时机。