0

我用cocos2d version2.0建游戏,没用ARC,发现一个问题:单例无效。

我用了两个单例宏,问题一样。

#ifndef SINGLETON_INTERFACE
#define SINGLETON_INTERFACE(CLASSNAME)                  \
    +(CLASSNAME*) sharedManager;
#endif

#ifndef SINGLETON_IMPLEMENTATION
#define SINGLETON_IMPLEMENTATION(CLASSNAME)             \
                                                        \
+(CLASSNAME*) sharedManager {                           \
    static dispatch_once_t pred;                        \
    static CLASSNAME* shared##CLASSNAME = nil;          \
    dispatch_once( &pred, ^{                            \
    shared##CLASSNAME = [[self alloc] init]; });        \
    return shared##CLASSNAME;                           \
}                                                           
#endif

或者

#ifndef SINGLETON_INTERFACE
#define SINGLETON_INTERFACE(CLASSNAME)              \
    +(CLASSNAME*) sharedManager;
#endif

#ifndef SINGLETON_IMPLEMENTATION            
#define SINGLETON_IMPLEMENTATION(CLASSNAME)         \
\
static CLASSNAME* shared##CLASSNAME = nil;          \
\
+(CLASSNAME*) sharedManager                         \
{                                                   \
    if (shared##CLASSNAME != nil) {                 \
        return shared##CLASSNAME;                   \
    }                                               \
\
    @synchronized(self) {                           \
        if (shared##CLASSNAME == nil) {             \
            shared##CLASSNAME = [[self alloc] init];\
        }                                           \
    }                                               \
\
    return shared##CLASSNAME;                       \
}                                                   \
\
+(id) allocWithZone:(NSZone*)zone                   \
{                                                   \
    @synchronized(self) {                           \
        if (shared##CLASSNAME == nil) {             \
            shared##CLASSNAME = [super allocWithZone:zone]; \
            return shared##CLASSNAME;               \
        }                                           \
    }                                               \
    NSAssert(NO, @ "[" #CLASSNAME " alloc] explicitly called on singleton class.");   \
    return nil;                                     \
}                                                   \
\
-(id) copyWithZone:(NSZone*)zone                    \
{                                                   \
    return self;                                    \
}                                                   \
\
-(id) retain                                        \
{                                                   \
    return self;                                    \
}                                                   \
\
-(unsigned) retainCount                             \
{                                                   \
    return UINT_MAX;                                \
}                                                   \
\
-(oneway void) release                              \
{                                                   \
}                                                   \
\
-(id) autorelease                                   \
{                                                   \
    return self;                                    \
}
#endif

利用:

[[CCDirector sharedDirector] replaceScene:[MenuScene sharedManager]];

MenuScene 再次显示,但任何按钮(CCMenu)或其他元素(CCNode)都没有响应。我的意思是第一次调用,场景一切正常,再次调用时,场景显示但菜单或其他元素没有响应。但是在cocos2d v1.0 运行非常好。

///////////////////////////////////////// ///////////////

我在没有“[super cleanup]”的情况下覆盖了“cleanup”,如下所示:

-(void) dealloc
{   
    [super cleanup];
    [super dealloc];
}

-(void) cleanup 
{
    //
}

现在,运行单例的场景没问题,但它安全吗?

4

1 回答 1

2

问题可能在于 CCDirector 对场景的子节点执行“清理”操作。

cocos2d v2.0 在几种情况下增加了对块的使用,这些块在“清理”期间被释放,无论你的单例是否留在内存中。

从 v2.0 迁移指南:

将清理标志设置为 YES 可能会在您的应用程序逻辑中产生副作用,该逻辑仍在对已释放资源进行隐式引用。CCMenuItems,它在内部使用块来启动操作,可能会出现问题并且不启动操作,假设您已经从其父节点中删除了项目并激活了清理标志并将其添加回来,这是一个明显的迹象之一。只需将标志更改为 NO 就足够了。

迁移指南:http ://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:migrate_to_v2.0#ccsprite


副手,我建议你:

  • 找到一种方法来安全地防止对您的单身孩子进行“清理”。
  • 或者:将所有内容作为您显示/隐藏的 CCLayer 的子项保存在内存中,而不是使用场景机制。
  • 或者:不要使用单例,每次都重新创建你的场景。
于 2012-06-05T15:34:18.223 回答