0

J'essaie d'écrire ma petite application et de rencontrer des problèmes de gestion de la mémoire. Au début, j'ai Game objet singleton à la propriété:Gestion de la mémoire de la propriété de Singleton

//Game.h 
@interface Game : NSObject 

@property (nonatomic, retain) MapBuildingsLayer *mapBuildingsLayer; 

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

@end 

MapBuildingsLayer est juste Cocos2d CCLayer exemple

//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 

Dans MapBuildingsLayer.m 'méthode de init J'utilise Game' mapBuildingsLayer propriété de stocker une référence à cette instance CCLayer dans mon singleton (pour une utilisation future dans d'autres méthodes):

//MapBuildingsLayer.m 
@implementation MapBuildingsLayer 

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

Lorsque j'appelle la méthode addObject:objName At: de Game, mon application tombe en panne avec EXC_BAD_ACCESS. Comment dois-je déclarer la propriété dans Game singleton pour l'utiliser à partir d'autres endroits dans la vie de mon application?

+0

Essayez d'activer NSZombieEnabled et voir quelle information supplémentaire qui vous donne (http: // stackoverflow.com/questions/2190227/how-do-i-set-nszombieenabled-in-xcode-4) – Rengers

+0

@Rengers L'activation de zombies n'ajoute aucune ligne supplémentaire au journal de débogage. –

+0

où mapBuildingLayer est-il alloué init? – bryanmac

Répondre

0

En général, vous ne pas utiliser le singleton dans la classe elle-même, essayez de changer

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

à

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

Vous devriez être en utilisant [Game game] externe à la classe pour entrer dans l'instance singleton de votre classe et appeler ses méthodes, mais interne à la classe, vous vous référez simplement à lui comme normal.

Généralement, si vous utilisez un jeu singleton, ce n'est pas comme ça que vous l'utiliseriez. Essayez de penser comme ça avec une machine à états géante, créez une sous-classe CCScene qui va initialiser toutes vos sous-classes CCLayer respectives et les contrôler. Ensuite, à partir de l'appareil, vous pouvez charger l'initialisation appropriée de sa scène et cela créera tout en dessous.

Dans votre méthode applicationDidFinishLaunching, il suffit que votre objet singleton charge votre première scène. Je recommande vraiment de vérifier le Learning Cocos2d Book car il couvre très bien ce moteur d'état singleton et je pense que éclaircir toutes vos questions.

La ligne de fond est que le moteur d'état charge la scène qui charge les couches.

+0

Merci pour le conseil! Mais changer [Game game] '' [self] 'n'a pas corrigé le crash. –

+0

Assurez-vous que la propriété mapBuildingsLayer est nulle à ce stade. –

+0

Oui, cette propriété est généralement 'nil', puis après l'initialisation de' MapBuildingsLayer', elle est définie sur l'adresse correcte (je viens de la vérifier via le débogage). Je veux dire, mon instance de 'MapBuildingsLayer' a l'adresse' 0xAABBCC' par exemple et la valeur de '[Game game] .mapBuildingsLayer' est également définie sur' 0xAABBCC' au moment du crash. –

0

Aucun endroit où votre code mapBuildingsLayer est initialisé. Je l'espère, avant de retourner votre exemple, vous devriez aussi faire

instance.mapBuildingsLayer = [CCLayer alloc] init]; 
+0

Bien sûr j'ai la ligne suivante: 'MapBuildingsLayer * buildings = [Noeud MapBuildingsLayer];' dans mon code. Mon instance 'MapBuildingsLayer' est initialisée et fonctionne correctement (capture d'événements tactiles par exemple). –

+0

@Saran: Bien que vous ayez raison, ce n'est probablement pas la cause de l'accident. S'il n'est pas initialisé, il sera nul, et envoyer des messages à zéro ne causera pas de plantage. En passant, ce code devrait être plus proche de 'instance.mapBuildingsLayer = [[[MapBuildingsLayer alloc] init] autorelease]'; – Rengers

0

Je pense que la façon dont vous attribuez mapBuildingsLayer est incorrecte. Retirer [Game game].mapBuildingsLayer = self de votre méthode d'initialisation MapBuildingsLayer et au lieu d'ajouter les éléments suivants à l'intérieur Game méthode init:

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

maintenant il est initialisé dans votre méthode singleton init afin que vous puissiez accéder simplement comme [Game game].mapBuildingsLayer partout en dehors de la classe Game. Si cela ne marche pas, essayez de poster ce que fait addPitAt:.

espérons que cette aide