2009-01-09 5 views
1

J'utilise des instruments pour essayer de déterminer s'il y a des endroits dans mon application que je pourrais être plus efficace avec l'utilisation de la mémoire. J'ai pris le temps de me familiariser avec les instruments, mais je suis généralement un débutant avec des problèmes de gestion de la mémoire de chasse provenant d'un arrière-plan Java. Je semblent utiliser à propos 1.82MB par des appels à cette méthode:Débogage de la mémoire de l'iPhone

+ (NSString *)stringFromDateWithFormat:(NSDate *)date withFormat:(NSString *)format 
{ 
    NSDateFormatter *dateFormatter; 
    NSString *result; 

    if (nil == date || nil == format) 
     return nil; 

    result = nil; 
    if (nil != (dateFormatter = [[NSDateFormatter allocWithZone:[self zone]] init])) { 
     [dateFormatter setDateFormat:format]; 

     if (nil != (result = [dateFormatter stringFromDate:date])) { 
      [dateFormatter release]; 
      return result; 
     } 

     [dateFormatter release]; 
    } 
    return nil; 
} 

Comme je publie la formatter ce jour, je me demande si le résultat NSString est mon problème. Il me semble que l'appel de la librairie stringFromDate retournerait un objet autoreleased donc je ne peux rien faire pour le 'manuellement' le gérer. Un peu incertain de la façon d'optimiser cette méthode.

Répondre

4

Cette méthode est appelée plusieurs fois dans une boucle? Les objets libérés ne sont libérés que lorsque NSAutoreleasePool est libéré. Si je comprends bien, le pool autorelease par défaut est créé et libère chaque boucle d'événement. Il est possible que vous créiez trop d'objets autoreleased au cours d'une boucle d'événement unique. La solution consiste à créer votre propre NSAutoreleasePool dans un endroit approprié et à le libérer pour effacer les objets autoreleased. Un exemple extrême qui illustre le point:

int i; 
NSAutoreasePool* pool = nil; 
for (i = 0; i < 1000000; ++i) { 
    /* Create a new pool every 10000 iterations */ 
    if ((i % 10000) == 0) { 
     if (pool) [pool release]; 
     pool = [[NSAutoreleasePool alloc] init]; 
    } 
    [someObj someMethodThatCreatesAutoreleasedObjects]; 
} 
[pool release]; 

Dans cet exemple, la piscine actuelle est libéré 10.000 itérations et un nouveau est créé. Vous pouvez en savoir plus sur la gestion de la mémoire dans la section Memory Management Programming Guide sur les pools de libération automatique.

0

De toute façon, vous devez renvoyer un objet autoreleased, donc vous ne devriez rien faire à propos de la chaîne de résultats. Je ne vois aucune erreur liée à la mémoire, mais votre code est nettement plus verbeux que nécessaire. Gardez à l'esprit que dans Objective-C, si vous appelez une méthode sur zéro, vous récupérez zéro (ou 0 pour un entier, mais pas pour les valeurs à virgule flottante). Vous pouvez supprimer toutes ces instructions if et les deux chemins de retour, et votre code fonctionnera toujours de la même manière. De plus, j'utiliserais simplement alloc au lieu de allocWithZone.

+0

Pouvez-vous dire pourquoi vous n'utilisez pas allocWithZone? – Rob

+0

Pour une utilisation normale, ce n'est pas nécessaire car vos objets seront toujours alloués sur la même zone par défaut. Voir cet article: http://developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/MemoryMgmt/Concepts/Zones.html –

0

Je ne suis pas à 100% avec ça. Je suis également en train d'apprendre le développement de Mac/Iphone. Mais vous pouvez utiliser le pool de publication automatique pour faciliter la gestion de la mémoire. Il est utilisé pour contourner les problèmes de libération.

Voici un article avec beaucoup sur memory management. Consultez le menu de gauche.