2010-10-05 7 views
0

Je reçois des fuites de mémoire pointant vers la ligne « NSDictionary *dw = [NSDictionary dictionaryWithContentsOfFile:path]; » en utilisant le code suivantNSDictionary comme des biens

NSDictionary *_allData; 

@property (nonatomic, retain) NSDictionary *allData; 

@synthesize allData = _allData; 

+ (NSString*)getNSPath 

{ 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 

NSString *documentsDirectory = [paths objectAtIndex:0]; 

NSString *path = [documentsDirectory stringByAppendingPathComponent:@"alarm.plist"]; 

return path; 
} 


- (NSDictionary *)allData 
{ 
NSString *path = [saveAlarm getNSPath]; 
NSDictionary *dw = [NSDictionary dictionaryWithContentsOfFile:path]; 


_allData = [NSDictionary dictionaryWithDictionary:dw]; 

    return _allData; 
} 

Les données changent dans le pList et quand je demande de récupérer ce qui est nouveau là par PROPERTY elle fuites. Toute recommandation sur la façon de le rendre clair? Ou comment mettre en œuvre ce genre de chose sans fuites?

Merci

Répondre

2

Vous devez libérer _allData avant réaffectant. Vous devez également le conserver lorsque vous l'attribuez.

EDIT: Intégration de l'amélioration de Robert pour se débarrasser d'un NSDictionary non nécessaire. Parce que vous renvoyez un objet à travers une limite d'API, il doit être renvoyé en tant qu'objet auto-libéré.

- (NSDictionary *)allData 
{ 
    NSString *path = [saveAlarm getNSPath]; 
    [_allData release]; 
    _allData = [[NSDictionary dictionaryWithContentsOfFile:path] retain]; 

    return [_allData autorelease]; 
} 

Le code affiché est un peu bizarre, vous créez une propriété appelée AllData, à utiliser dire _allData comme Ivar (avec @synthesize), puis la mise en oeuvre d'un getter personnalisé qui définit la Ivar. Si vous déclarez la propriété en lecture seule, vous pouvez supprimer l'instruction @synthesize.

Si vous n'utilisez que _allData dans cette méthode et nulle part ailleurs dans cette classe, vous pouvez vous en débarrasser complètement. Voici une version simplifiée beaucoup qui fait la même chose:

- (NSDictionary *)allData 
{ 
    NSString *path = [saveAlarm getNSPath]; 
    return [NSDictionary dictionaryWithContentsOfFile:path]; 
} 
+0

Cette solution provoque une fuite de mémoire de 864 octets sur la ligne où la conservation a été ajoutée. Je ne sais pas pourquoi je devrais le conserver quand c'est la méthode de classe. – Vanya

+0

Ah. Lorsque vous renvoyez un objet via les limites de l'API, vous devez le renvoyer comme auto-libéré. Je vais mettre à jour le code. –

+0

Vous devez le conserver car vous le stockez dans un ivar. Sinon, l'objet sera libéré pendant que votre ivar a encore une référence à lui. –

0

Pourquoi ne vous remplace pas

NSDictionary *dw = [NSDictionary dictionaryWithContentsOfFile:path]; 


_allData = [NSDictionary dictionaryWithDictionary:dw]; 

Avec

_allData = [NSDictionary dictionaryWithContentsOfFile:path]; 

Ensuite, vous n'avez pas à vous soucier de la dw Autorelease NSDictionary qui est probablement à l'origine de votre fuite.

+0

C'est une bonne suggestion en ce que c'est beaucoup moins de code et vous ne créez pas un dictionnaire supplémentaire, mais cela fuirait encore. La fuite est due au fait que vous affectez un nouveau NSDictionary à _allData sans libérer au préalable la valeur existante. –

+0

Cette solution ne fait pas de fuites au départ, mais peu de fuite (32 octets) quand je demande de nouvelles valeurs à récupérer .... donc pas de progrès jusqu'à présent – Vanya