Управление памятью свойств синглтона - PullRequest
0 голосов
/ 17 сентября 2011

Я пытаюсь написать свое маленькое приложение и у меня возникают проблемы с управлением памятью. Сначала у меня есть 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 init я использую свойство Game mapBuildingsLayer для хранения ссылки на этот экземпляр CCLayer в моем синглтоне (для будущего использования в других методах):

//MapBuildingsLayer.m
@implementation MapBuildingsLayer

-(id) init
{
    if( (self=[super init])) {
        [Game game].mapBuildingsLayer = self;
    }
    return self;
}

Когда я вызываю Game метод addObject:objName At:, мое приложение вылетает с EXC_BAD_ACCESS. Как я должен объявить свойство в Game singleton, чтобы использовать его из других мест в жизни моего приложения?

Ответы [ 3 ]

0 голосов
/ 17 сентября 2011

Обычно вы не используете синглтон в самом классе, попробуйте изменить

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

до

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

Вы должны использовать [Game game] вне класса, чтобы попасть в одноэлементный экземпляр вашего класса и вызывать его методы, но внутри класса вы бы просто называли его как self, как обычно.

Обычно, если вы собираетесь использовать игровой синглтон, это не то, как вы его используете. Попробуйте думать об этом так, используя гигантский конечный автомат. Создайте подкласс CCScene, который будет инициализировать все ваши соответствующие подклассы CCLayer и управлять ими. Затем из машины состояний вы можете загрузить соответствующую инициализирующую ее сцену, и это создаст все под ней.

В вашем методе applicationDidFinishLaunching вы просто используете свой одноэлементный объект для загрузки вашей первой сцены. Я бы действительно рекомендовал ознакомиться с Learning Cocos2d Book , так как он очень хорошо описывает этот движок синглтона, и я думаю, что проясню все ваши вопросы.

Итог: государственный двигатель загружает сцену, которая загружает слои.

0 голосов
/ 18 сентября 2011

Я думаю, что вы назначаете mapBuildingsLayer неправильно.Удалите [Game game].mapBuildingsLayer = self из вашего метода инициализации MapBuildingsLayer и вместо этого добавьте следующий метод Game init:

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

, теперь он инициализируется в вашем методе singleton init, чтобы вы могли получить к нему доступ просто как [Game game].mapBuildingsLayer где-нибудь за пределами класса Game.Если это не работает, попробуйте опубликовать, что делает addPitAt:.

надеюсь, это поможет

0 голосов
/ 17 сентября 2011

Нет, где в вашем коде я вижу инициализацию вашего mapBuildingsLayer.Я надеюсь, что прежде чем вернуть свой экземпляр, вы должны также сделать

instance.mapBuildingsLayer = [CCLayer alloc] init];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...