J'ai créé une liste de propriétés qui, lorsqu'elle n'est pas archivée, initialise un tableau d'instances d'une classe appelée 'SelectableObject'. La classe SelectableObject ne contient pas de méthode init, elle est juste un conteneur pour certaines variables d'instance et est bien entendu conforme à NSCoding.Obligation de conserver une nouvelle instance d'une classe et, par conséquent, une fuite de mémoire
Lorsqu'un objet SelectableObject est choisi, j'initialise une nouvelle instance d'une sous-classe de SelectableObject, en fonction de l'objet sélectionné. Appelez ce 'AnimalObject'.
J'ai écrit un initialiseur personnalisé pour AnimalObject, qui prend un objet SelectableObject comme argument, pour obtenir les valeurs de SelectableObject, puis ajoute une partie de sa propre valeur. Ainsi, la méthode ressemble à ceci:
- (AnimalObject *)initWithObject:(SelectableObject *)selectedObject
Et je l'appelle de l'écran de sélection comme ceci:
AnimalObject *animal = [[AnimalObject alloc] initWithObject:self.selectedObject];
où self.selectedObject est l'objet sélectionné à partir de l'écran de sélection.
Maintenant, dans le initialiseur pour la AnimalObject, je mis les valeurs initiales, puis juste avant de le retourner, appelez
[self saveToFile];
pour enregistrer le nouvel objet fichier. Donc, après l'avoir initialisé dans l'écran de sélection, je devrais pouvoir le relâcher tout de suite, n'est-ce pas?
Cependant, si je tente de le libérer, i.e.
AnimalObject *animal = [[AnimalObject alloc] initWithObject:self.selectedObject];
[animal release];
je reçois un accident.
Si je ne le libère pas, je reçois un avertissement que tous les iVars initialisés dans l'initialiseur AnimalObject fuient la mémoire.
J'ai essayé de créer une propriété AnimalObject dans le selectionScreen et attribuer le nouvel objet à libérer avant, mais cela se bloque encore, à savoir
self.newAnimal = animal;
[animal release];
Je me demande si ma description ci-dessus, je Je fais quelque chose de très mal? Comme enregistrer une classe à partir de son initialiseur. Ou en passant une classe parent en tant qu'objet à un initiateur d'une sous-classe ... Je ne suis pas vraiment sûr pourquoi je ne peux pas libérer l'instance de l'objet que j'ai créé.
Merci pour toute aide!
EDIT Ok, voici mon code:
La classe sélectionnable de l'objet:
#define kObjectNumberKey @"ObjectNumber"
#define kObjectTypeKey @"Type"
#define kObjectNameKey @"Name"
#define kObjectThumbKey @"Thumb"
#define kObjectMainKey @"Main"
#import <Foundation/Foundation.h>
@interface SelectableObject : NSObject <NSCoding> {
int number;
NSString *type;
NSString *name;
NSString *thumbString;
NSString *mainString;
}
@property (nonatomic, assign) int number;
@property (nonatomic, retain) NSString *type;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *thumbString;
@property (nonatomic, retain) NSString *mainString;
@end
#import "SelectableObject.h"
@implementation SelectableObject
@synthesize number;
@synthesize type;
@synthesize name;
@synthesize thumbString;
@synthesize mainString;
- (void)dealloc {
NSLog(@"Selectable Object DEALLOC");
[name release];
[type release];
[thumbString release];
[mainString release];
[super dealloc];
}
#pragma mark -
#pragma mark NSCoding
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeInt:self.number forKey:kObjectNumberKey];
[aCoder encodeObject:self.type forKey:kObjectTypeKey];
[aCoder encodeObject:self.name forKey:kObjectNameKey];
[aCoder encodeObject:self.thumbString forKey:kObjectThumbKey];
[aCoder encodeObject:self.mainString forKey:kObjectMainKey];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
self.number = [aDecoder decodeIntForKey:kObjectNumberKey];
self.type = [aDecoder decodeObjectForKey:kObjectTypeKey];
self.name = [aDecoder decodeObjectForKey:kObjectNameKey];
self.thumbString = [aDecoder decodeObjectForKey:kObjectThumbKey];
self.mainString = [aDecoder decodeObjectForKey:kObjectMainKey];
}
return self;
}
@end
Le code dans un autre VC pour créer un nouvel objet animal avec les détails du selectedObject:
- (void)createNewAnimal {
self.selectedObject.name = self.nameField.text;
Animal *animal = [[Animal alloc] initWithObject:self.selectedObject];
// [animal release]; (causes it to crash)
// Initialise the new Root Controller and load with selected object
}
Et dans la classe Animal:
- (Animal *)initWithObject:(SelectableObject *)selectedObject {
if (self = [super init]) {
//Initialise all the values
dateCreated = [[NSDate alloc] init];
dateLastUsed = [[NSDate alloc] init];
name = selectedObject.name;
thumbString = selectedObject.thumbString;
mainString = selectedObject.mainString;
}
[self saveToFile];
return self;
}
Je ne vois rien d'anormal dans votre description. Cela aiderait à voir le code dans 'initWithObject:' et les déclarations pour vos propriétés dans 'AnimalObject'. En outre, le code de votre méthode 'dealloc' peut également fournir des indices. –
Est-ce que 'selectedObject' est retenu? Ce n'est peut-être pas 'animalObject' qui est le problème, mais ce que vous transmettez en tant que paramètre init. –
Je pense que vous avez raison Stephen. selectedObject est conservé, et si je commente sa sortie dans la méthode dealloc, le programme fonctionne bien! Mis à part le fait qu'il n'est pas libéré bien sûr. Donc je ne devrais pas passer un objet parent retenu en tant que paramètre d'un initialiseur de sa sous-classe? Hmmm - comment puis-je transmettre les détails de l'objet sélectionné tout en libérant l'objet selectedObject? – Smikey