Вынужден сохранить новый экземпляр класса и, следовательно, утечка памяти - PullRequest
0 голосов
/ 23 ноября 2010

Я создал список свойств, который при разархивировании инициализирует массив экземпляров класса с именем «SelectableObject».Класс SelectableObject не содержит метод init, он является просто контейнером для некоторых переменных экземпляра и, конечно, соответствует NSCoding.

Когда выбран SelectableObject, я инициализирую новый экземпляр подкласса SelectableObject, в зависимости от того, какой объект был выбран.Назовите это AnimalObject.

Я написал собственный инициализатор для AnimalObject, который принимает SelectableObject в качестве аргумента, чтобы получить значения SelectableObject, а затем добавляет некоторые его собственные значения.Таким образом, метод выглядит следующим образом:

- (AnimalObject *)initWithObject:(SelectableObject *)selectedObject

И я вызываю его на экране выбора следующим образом:

AnimalObject *animal = [[AnimalObject alloc] initWithObject:self.selectedObject];

где self.selectedObject - это объект, выбранный на экране выбора.

Теперь в инициализаторе AnimalObject я устанавливаю начальные значения, а затем, перед тем, как его вернуть, вызываю

[self saveToFile];

, чтобы сохранить новый объект в файл.Так что, инициализировав его на экране выбора, я сразу же смогу выпустить его, верно?

Однако, если я попытаюсь отпустить его, то есть

    AnimalObject *animal = [[AnimalObject alloc] initWithObject:self.selectedObject];
[animal release];

, я получу сбой.

Если я не отпущу его, я получу предупреждение, что все iVars, инициализированные в инициализаторе AnimalObject, имеют утечку памяти.

Я пытался создать свойство AnimalObject в selectionScreen и назначить ему новый объект перед выпуском, но это все равно дает сбой, т.е.

self.newAnimal = animal;
[animal release];

Мне интересно, если из моего описаниявыше я что-то делаю очень неправильно?Как сохранение класса из инициализатора.Или передача родительского класса в качестве объекта инициализатору подкласса ... Я не совсем уверен, почему не могу выпустить экземпляр созданного мной объекта.

Спасибо за любую помощь!

РЕДАКТИРОВАТЬ Хорошо, вот мой код:

Выбираемый класс объекта:

#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

Код в другом VC для создания нового объекта Animal с деталями 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
}

И в классе животных:

- (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;
}

Ответы [ 4 ]

1 голос
/ 23 ноября 2010

Возможно, ваш initWithObject немного подозрительный. Делалок животного выпускает name, thumbString и mainString? Если так, то их выпускают дважды.

- (Animal *)initWithObject:(SelectableObject *)selectedObject {
    if (self = [super init]) {
        //Initialise all the values
        dateCreated = [[NSDate alloc] init];
        dateLastUsed = [[NSDate alloc] init];
        name = [selectedObject.name retain]; // Added retain
        thumbString = [selectedObject.thumbString retain]; // Added retain
        mainString = [selectedObject.mainString retain]; // Added retain
    }   
    [self saveToFile];
    return self;
}
1 голос
/ 23 ноября 2010

Как выглядит метод dealloc () для Animal? Вы выпускаете name, thumbString и mainString там? Если да, то это ваш сбой.

Из-за самой быстрой проблемы на западе ответ был уже предоставлен @imaginaryboy. Поскольку mainString и thumbString освобождаются в суперклассе, происходит сбой. Просто добавьте сохранение в методе init, и все будет готово.

Примечание: NSString должны использовать копию вместо сохранения.

0 голосов
/ 23 ноября 2010

Я не знаю, в этом ли проблема здесь, но до сих пор я видел только методы init, которые возвращают тип идентификатора, например

- (id)init

Я не пытался вернуть другой тип, кромедо сих пор.

0 голосов
/ 23 ноября 2010

Это полный выстрел в темноте, но вы пробовали

  AnimalObject *animal = [[[AnimalObject alloc] initWithObject:self.selectedObject] autorelease];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...