CCLayer 在 init 中调用 schedual 方法后引用计数混乱的有关问题

CCLayer 在 init 中调用 schedual 方法后引用计数混乱的问题

参考相关问题链接:

http://www.cocos2d-iphone.org/forum/topic/314

先上代码再解释:

RefferenceCountLayer.h

//
//  RefferenceCountLayer.h
//  HungryBear
//
//  Created by Bruce Yang on 12-8-9.
//  Copyright (c) 2012年 EricGameStudio. All rights reserved.
//

#import "cocos2d.h"

@interface RefferenceCountLayer : CCLayer

@end


RefferenceCountLayer.mm
//
//  RefferenceCountLayer.mm
//  HungryBear
//
//  Created by Bruce Yang on 12-8-9.
//  Copyright (c) 2012年 EricGameStudio. All rights reserved.
//

#import "RefferenceCountLayer.h"

@implementation RefferenceCountLayer

-(ccColor4B) randomBrightColor {
    while(true) {
        float requiredBrightness = 192;
        ccColor4B randomColor = ccc4(arc4random() % 255, 
                                     arc4random() % 255, 
                                     arc4random() % 255, 
                                     255);
        if (randomColor.r > requiredBrightness || 
            randomColor.g > requiredBrightness ||
            randomColor.b > requiredBrightness) {
            return randomColor;
        }        
    }
}

-(id) init {
    if((self = [super init])) {
        self.isTouchEnabled = YES;
        
        ccColor4B color4B = [self randomBrightColor];
        CCLayerColor* lyrColor = [CCLayerColor layerWithColor:color4B];
        [self addChild:lyrColor];
        
        NSLog(@"init() -> 1.RefferenceCount = %d", [self retainCount]);
        
        [self schedule:@selector(tick:)];
        
        NSLog(@"init() -> 2.RefferenceCount = %d", [self retainCount]);
    }
    return self;
}

-(void) draw {
    NSLog(@"draw() -> RefferenceCount = %d", [self retainCount]);
}

-(void) tick:(ccTime)dt {
    NSLog(@"tick() -> RefferenceCount = %d", [self retainCount]);
}

-(void) ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
    NSLog(@"ccTouchesBegan()");
    [[CCDirector sharedDirector] replaceScene:[RefferenceCountLayer node]];
}

-(void) dealloc {
    NSLog(@"ReffenceCountLayer.dealloc!");
    [super dealloc];
}

@end


控制台输出如下:

2012-08-09 00:41:55.733 WonderPipeEffects1[18926:707] init() -> 1.RefferenceCount = 1
2012-08-09 00:41:55.737 WonderPipeEffects1[18926:707] init() -> 2.RefferenceCount = 2
2012-08-09 00:41:55.741 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.748 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.753 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.758 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.769 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.775 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.785 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.788 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.803 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.807 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.818 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.820 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.836 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.839 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.852 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.856 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.869 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.872 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.886 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.889 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.907 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.911 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.917 WonderPipeEffects1[18926:707] ccTouchesBegan()
2012-08-09 00:41:55.921 WonderPipeEffects1[18926:707] init() -> 1.RefferenceCount = 1
2012-08-09 00:41:55.925 WonderPipeEffects1[18926:707] init() -> 2.RefferenceCount = 2
2012-08-09 00:41:55.928 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 3
2012-08-09 00:41:55.932 WonderPipeEffects1[18926:707] ReffenceCountLayer.dealloc!
2012-08-09 00:41:55.936 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.940 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.944 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.952 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.954 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.970 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.980 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4

测试结论如下:

init 方法里面调用 schedual 方法以后,RefferenceCountLayer 的引用计数会加1,这里没有问题~

但是到了 draw()、tick() 方法里面,引用计数竟然由 2 直接跳到 4!

我是百思不得其解,不过经过我的测试,发现引用计数虽然直接跳到 4 了,

但是在 replaceScene 的时候,依然能够看到 RefferenceCountLayer 的 dealloc 方法被调用了,

也就是说,该对象并不会因此而出现什么内存泄露的问题~

后面我思考了一下,引用计数由 2 跳到 4 肯定是在 cocos2d 框架内部安全的增长到 4 的,

这个不用我们去操心,没有内存泄露,我们知道这样一件事情就行了~

前面附的链接里面 cocos2d 作者之一 Riq 没有就此问题做较为仔细的回复,这是问题的来源,

不过也不能去责怪他什么,人的精力毕竟是有限的,他不可能就每个问题都做详细的回复,

凡事都往好的方面想,Riq 作为 cocos2d 的主要负责人之一,为我们提供了这么 nice 的东西,这样便行了~