0

Lorsque je compile avec l'analyseur, j'obtiens quelques messages. J'ai ces propriétés ont déclaré:Messages "Décrément incorrect" et "Fuite potentielle" de l'analyseur

@property (nonatomic, retain) SyncServicePrimary *syncAndCartOne; 
@property (nonatomic, retain) SyncServiceSecondary *syncAndCartTwo; 

Cette méthode est appelée à partir applicationDidBecomeActive et je reçois « fuite potentielle d'un objet alloué ».

-(void)makeTheCartObjectsForCountry:(NSString*)country_key{ 
    self.syncAndCartOne = [[SyncServicePrimary alloc] init]; 
    self.syncAndCartTwo = [[SyncServiceSecondary alloc] init]; 
} 

Ceci est appelé dans applicationWillResignActive; ici je reçois "Décrément incorrect du compte de référence d'un objet".

-(void) removeTheCartObjects{ 
    [self.syncAndCartOne release]; 
    self.syncAndCartOne = Nil;  
    [self.syncAndCartTwo release]; 
    self.syncAndCartTwo = Nil; 
} 

Si je mets les objets à autorelease, l'erreur disparaît, mais je veux que les objets soient libérés lorsque l'application se cache.

Est-ce que c'est quelque chose que je fais bien mais qui est divisé trop loin pour que l'analyseur voit le début et la fin, ou est-ce quelque chose que je peux faire mieux pour ne pas me plaindre?

Il est plus que probable que je manque un concept simple en ce qui concerne release et alloc cycles (je viens de PHP et C#).

+2

Notez que 'Nil' est le littéral NULL pour les pointeurs de classe. Pour les pointeurs d'objet, vous devriez utiliser 'nil' à la place. –

+0

bon à savoir, merci. –

+0

Juste pour le conduire à la maison, si je fais un contrôle nul sur une instance d'une classe; l'utilisation d'un "== Nil" n'est pas la même chose que "== nil"? –

Répondre

4

Votre problème est ici:

-(void)makeTheCartObjectsForCountry:(NSString*)country_key{ 
    self.syncAndCartOne = [[SyncServicePrimary alloc] init]; 
    self.syncAndCartTwo = [[SyncServiceSecondary alloc] init]; 
} 

Vous créez les objets, puis de les retenir (en raison de la déclaration de la propriété), donc ils ont un compte de référence de 2, quand un seul objet est de leur référencement .

Vous devriez le faire comme ceci:

-(void)makeTheCartObjectsForCountry:(NSString*)country_key{ 
    SyncServicePrimary *primary = [[SyncServicePrimary alloc] init]; 
    self.syncAndCartOne = primary; 
    [primary release]; 

    SyncServiceSecondary *secondary = [[SyncServiceSecondary alloc] init]; 
    self.syncAndCartTwo = secondary; 
    [secondary release]; 
} 
+0

Ou utilisez '-autorelease'. –

+2

Autoreleasing tout semble juste comme une pratique paresseuse pour moi. Bien sûr, c'est parfois nécessaire, mais il est toujours préférable de gérer votre mémoire directement. – EmilioPelaez

+0

Et c'est toujours mieux parce que ...? –

2

Vous avez défini les propriétés avec attribut retain, de sorte que l'analyseur suppose que la méthode setter pour la propriété ressemble à ceci:

- (void)setSyncAndCartOne:(SyncServicePrimary *)newValue 
{ 
    [newValue retain]; 
    [self->_syncAndCartOne release]; // access the instance variable holding the property value 
    self->_syncAndCartOne = newValue; 
} 

Si vous utilisez @synthesize, la méthode setter va ressembler à ça.

Ainsi, lorsque makeTheCartObjectsForCountry: retours, l'objet syncAndCartOne a un retain nombre de 2, mais doit seulement avoir un nombre de retenir 1. C'est pourquoi l'utilisation autorelease corrige ce problème. Vous ne devriez pas faire [self.syncAndCartOne release] pour la même raison. La méthode setter enverra l'ancien objet release lorsque vous affectez nil à la propriété.

+0

Génial, il semble donc que je retiens deux fois et que je crée une ligne redondante avec l'appel = nil. Je voudrais pouvoir définir deux comme la réponse acceptée ... –

Questions connexes