Singleton的属性内存管理

时间:2011-09-17 13:11:16

标签: objective-c memory-management cocos2d-iphone properties

我正在尝试编写我的小应用程序并遇到一些内存管理问题。 首先,我有Game单例对象,其属性为:

//Game.h
@interface Game : NSObject

@property (nonatomic, retain) MapBuildingsLayer *mapBuildingsLayer;

+(Game *) game;
-(BOOL) addObject:(NSString *) objName At:(CGPoint) pt;

@end

其中MapBuildingsLayer只是cocos2d CCLayer实例

//Game.m
@implementation Game
@synthesize mapBuildingsLayer = _mapBuildingsLayer;

static Game *instance = nil;

+ (Game *)game {
    @synchronized(self) {
        if (instance == nil) {
            instance = [[Game alloc] init];
        }
    }
    return instance;
}

-(BOOL) addObject:(NSString *)objName At:(CGPoint)pt
{
    if([objName isEqualToString:OBJ_TYPE_PIT])
    {
        if([[Game game].mapBuildingsLayer addPitAt:pt]) //app crashes here
        {
            [self toggleConstructionMode];
            return YES;
        }
    }
    return NO;
}

@end

MapBuildingsLayer.m的{​​{1}}方法中,我使用init的{​​{1}}属性在我的单例中存储对此CCLayer实例的引用(以备将来在其他方法中使用) ):

Game

当我调用mapBuildingsLayer的{​​{1}}方法时,我的应用程序崩溃了//MapBuildingsLayer.m @implementation MapBuildingsLayer -(id) init { if( (self=[super init])) { [Game game].mapBuildingsLayer = self; } return self; } 。 如何在Game单例中声明属性以在我的应用程序生命周期中的其他位置使用它?

3 个答案:

答案 0 :(得分:0)

没有在您的代码中我看到您的mapBuildingsLayer已初始化。我希望在返回你的实例之前你也应该做

instance.mapBuildingsLayer = [CCLayer alloc] init];

答案 1 :(得分:0)

您通常不会在班级中使用单身人士,请尝试更改

        if([[Game game].mapBuildingsLayer addPitAt:pt]) //app crashes here

        if([self.mapBuildingsLayer addPitAt:pt]) //app crashes here

你应该在课堂外部使用[游戏]来进入你的类的单例实例并调用它的方法,但是在类的内部你只需将它称为自我就像正常一样。

通常情况下,如果您打算使用游戏单身,那么这不是您使用它的方式。尝试使用巨型状态机来思考它,创建一个CCScene子类,它将初始化所有相应的CCLayer子类并控制它们。然后从状态机中加载适当的初始化场景,并在其下创建所有内容。

在您的applicationDidFinishLaunching方法中,您只需让您的单例对象加载您的第一个场景。我真的建议查看Learning Cocos2d Book,因为它很好地涵盖了这个单例状态引擎,我认为会清除你所有的问题。

底线是让状态引擎加载加载图层的场景。

答案 2 :(得分:0)

我认为你分配mapBuildingsLayer的方式是错误的。从MapBuildingsLayer init方法中删除[Game game].mapBuildingsLayer = self,然后在Game init方法中添加以下内容:

self.mapBuildingsLayer = [[MapBuildingsLayer alloc] init] autorelease];

现在它已在您的单身init方法中初始化,因此您可以在[Game game].mapBuildingsLayer类之外的任何位置简单地将其作为Game进行访问。如果这不起作用,请尝试发布addPitAt:的内容。

希望这会有所帮助