代码之家  ›  专栏  ›  技术社区  ›  Smikey

强制保留类的新实例,因此泄漏内存

  •  0
  • Smikey  · 技术社区  · 14 年前

    我创建了一个属性列表,在未归档时,初始化一个名为“SelectableObject”的类的实例数组。SelectableObject类不包含init方法,它只是一些实例变量的容器,当然符合NSCoding。

    当选择SelectableObject时,我初始化SelectableObject子类的一个新实例,这取决于选择了哪个对象。称之为“AnimalObject”。

    我为AnimalObject编写了一个自定义的初始化器,它以SelectableObject作为参数,获取SelectableObject的值,然后添加一些自己的值。方法如下:

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

    我在选择屏幕上这样称呼它:

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

    其中self.selected object是从选择屏幕中选择的对象。

    现在,在AnimalObject的初始化器中,我设置了初始值,然后在返回之前,调用

    [self saveToFile];
    

    将新对象保存到文件。所以在选择屏幕上初始化后,我应该可以立即释放它,对吧?

    但是,如果我试图释放它,即

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

    我撞车了。

    如果我不释放它,就会得到一个警告:AnimalObject initialiser中初始化的所有ivar都在泄漏内存。

    我试过在selectionScreen中创建AnimalObject属性,并在释放之前将新对象分配给它,但这仍然会崩溃,即。

    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中创建新动物对象的代码,其中包含选定对象的详细信息:

    - (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 回复  |  直到 14 年前
        1
  •  1
  •   imaginaryboy    14 年前

    你的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;
    }
    
        2
  •  1
  •   Robert Höglund    14 年前

    动物的dealloc()方法看起来怎么样?你在里面放名字,拇指串和支柱吗?如果是,那就是你的崩溃。

    由于西方最快的枪械问题,答案已经由@imaginaryboy提供了。由于mainString和thumbString在超级类中被释放,它将崩溃。只要在init方法中添加一个retain,就应该设置好了。

    注: NSString s应该使用copy而不是retain。

        3
  •  0
  •   Andrew Carter    14 年前

    这是在黑暗中拍摄的完整照片,但你有没有试过

      AnimalObject *animal = [[[AnimalObject alloc] initWithObject:self.selectedObject] autorelease];
    
        4
  •  0
  •   dasdom    14 年前

    我不知道这是否是问题所在,但直到现在,我只看到init方法返回一个id类型,比如

    - (id)init
    

    到目前为止,我没有试图返回除id以外的其他类型。