[英]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是否釋放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;
}
動物的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.