簡體   English   中英

強制保留一個類的新實例,從而泄漏內存

[英]Forced to retain a new instance of a class and therefore leaking memory

我創建了一個屬性列表,在取消歸檔時,初始化一個名為“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];

我崩潰了

如果我不釋放它,我會收到一個警告,即在AnimalObject初始化器中初始化的所有iVars都在泄漏內存。

我嘗試在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中的代碼用SelectedObject的詳細信息創建一個新的Animal對象:

- (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類中:

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

您的initWithObject可能有點懷疑。 Animal的dealloc是否釋放namethumbStringmainString 如果是這樣,那么它們將被釋放兩次。

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

動物的dealloc()方法看起來如何? 您要在其中釋放名稱,thumbString和mainString嗎? 如果是的話,那就是你的崩潰。

由於西方問題最快的槍問題,答案已經由@imaginaryboy提供。 由於mainString和thumbString在超類中釋放,因此它將崩潰。 只需在init方法中添加一個保留,就可以完成所有工作。

注意: NSString應該使用copy而不是keep。

這是黑暗中的完整鏡頭,但您嘗試過嗎

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

我不知道這是否是這里的問題,但直到現在我才看到init方法返回一個id類型,比如

- (id)init

到目前為止,我還沒有嘗試返回ID以外的其他類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM