2010-05-07 7 views
0

J'ai quelques problèmes avec Objective-C et j'apprécierais certains pointeurs.Objective-C Problème hors de portée

J'ai une classe MapFileGroup qui a l'interface simple suivante (Il existe d'autres variables membres, mais ils ne sont pas importants):

@interface MapFileGroup : NSObject { 
NSMutableArray *mapArray; 

}

@property (nonatomic, retain) NSMutableArray *mapArray; 

mapArray est @synthesize « d dans le fichier .m

Il a une méthode init:

-(MapFileGroup*) init 
    { 
    self = [super init]; 
    if (self) 
    { 
     mapArray = [NSMutableArray arrayWithCapacity: 10]; 
    } 

    return self; 
    } 

Il a également une méthode pour ajouter un objet personnalisé au tableau:

-(BOOL) addMapFile:(MapFile*) mapfile 
{ 
if (mapfile == nil) return NO; 

mapArray addObject:mapfile]; 
return YES; 
} 

Le problème que je me vient quand je veux utiliser cette classe - évidemment en raison d'une mauvaise compréhension de la gestion de la mémoire de ma part.

Dans mon contrôleur de vue je déclare comme suit:

(dans le @interface):

MapFileGroup *fullGroupOfMaps;

Avec @property @property (nonatomic, retain) MapFileGroup *fullGroupOfMaps;

Puis dans le fichier .m J'ai fonction appelée loadMapData qui fait ce qui suit:

MapFileGroup *mapContainer = [[MapFileGroup alloc] init]; 
// create a predicate that we can use to filter an array 

// pour toutes les chaînes se terminant par .png (insensible à la casse) NSPredicate * caseInsensitivePNGFiles = [NSPredicate predicateWithFormat: @ "SELF endswith [c] '.png'"];

mapNames = [unfilteredArray filteredArrayUsingPredicate:caseInsensitivePNGFiles]; 
[mapNames retain]; 

NSEnumerator * enumerator = [mapNames objectEnumerator]; 
NSString * currentFileName; 
NSString *nameOfMap; 
MapFile *mapfile; 


while(currentFileName = [enumerator nextObject]) { 
    nameOfMap = [currentFileName substringToIndex:[currentFileName length]-4]; //strip the extension 

mapfile = [[MapFile alloc] initWithName:nameOfMap]; 
[mapfile retain]; 
// add to array 
[fullGroupOfMaps addMapFile:mapfile]; 

} 

Cela semble fonctionner ok (Même si je peux dire que je ne l'ai pas eu le travail sur la gestion de la mémoire correctement, je suis encore à apprendre Objective-C); Cependant, j'ai un (IBAction) qui interagit avec le fullGroupOfMaps plus tard. Il appelle une méthode au sein de fullGroupOfMaps, mais si j'interviens dans la classe à partir de cette ligne pendant le débogage, tous les objets fullGroupOfMaps sont maintenant hors de la portée et j'obtiens un plantage.

Alors excuses pour la longue question et une grande quantité de code, mais je suppose que ma principale question, il:

Comment dois-je gérer une classe avec un NSMutableArray comme une variable d'instance? Quelle est la bonne façon de créer des objets à ajouter à la classe afin qu'ils ne soient pas libérés avant que j'en ai fini avec eux?

Un grand merci

Répondre

2

Lorsque vous appelez [NSMutableArray arrayWithCapacity:], cela crée en fait un tableau “ autoreleased ”. Cela signifie qu'il sera publié automatiquement dans le futur. Habituellement, il sera libéré à la fin de la boucle d'exécution en cours.

Ce que vous voulez faire est de créer un tableau qui n'est pas autoeleased, parce que vous voulez le libérer explicitement quand vous avez fini avec lui. Pour ce faire, utilisez:

mapArray = [[NSMutableArray alloc] initWithCapacity: 10]; 

N'oubliez pas que vous devez le relâcher lorsque vous avez terminé. En règle générale, si une variable d'instance est initialisée dans la initialiseur de la classe, alors il devrait être libéré dans la méthode de la classe dealloc, comme ceci:

- (void) dealloc 
{ 
    [mapArray release]; 
    [super dealloc]; // so that NSObject can clean up itself 
} 

Certaines méthodes renvoient des objets autoreleased comme commodité pour vous, afin que vous n » Je dois gérer vous-même la mémoire (elle sera nettoyée automatiquement). Dans le cas des variables d'instance, vous ne voulez presque jamais qu'elles soient nettoyées automatiquement.

Vous pouvez également empêcher la libération automatique d'un objet autoreleased en le conservant de nouveau.

mapArray = [[NSMutableArray arrayWithCapacity:10] retain]; 

Le Cocoa Memory Management Programming Guide a quelques règles simples à suivre quand vous devez libérer explicitement, et quand vous devez conserver explicitement. Gardez le lien mis en signet jusqu'à ce que les règles soient devenues une seconde nature et vous n'aurez aucun problème avec Cocoa Memory Management. C'est beaucoup plus simple qu'il n'y paraît au départ (ou du moins, c'était le cas pour moi).

+0

Merci pour l'aide - J'ai lu les règles de gestion de la mémoire, mais toujours se trébucher de temps en temps (un peu trop habitué à nouveau et gratuit je pense). J'ai toujours un problème avec les objets qui sortent de la portée dans le tableau cependant, 'mapfile = [[MapFile alloc] initWithName: nameOfMap]; [mapfile retain]; // ajouter au tableau [fullGroupOfMaps addMapFile: mapfile]; 'est en train de les ajouter correctement mais ils sont hors de portée. Je pensais que addObject effectuerait une retenue? – davbryn

+0

Mon mauvais, entre C++ et Obj-C ne rend pas la vie facile. J'avais créé le @properties pour mes classes mais n'utilisant pas self.variable_name pour obtenir/définir ainsi aucune retenue avait lieu :( – davbryn