自定义对象中decodeObjectForKey的内存泄漏

时间:2010-12-06 02:31:00

标签: iphone objective-c memory-leaks instruments

尝试从NSUserDefaults加载保存的自定义对象时遇到了泄漏。这是代码的罪魁祸首。有没有人看到任何明显错误的东西?

@interface CustomQuery : NSObject <NSCoding> {
 NSString *theTitle;
 NSString *query;
}

@property(nonatomic, retain) NSString *theTitle;
@property(nonatomic, retain) NSString *query;

- (id)initWithCoder:(NSCoder *)aDecoder {

if (self = [super init]) {
    //tempTitle is leaking
    NSString *tempTitle = [[aDecoder decodeObjectForKey:@"QueryTitle"] retain];
    self.theTitle = tempTitle;
    [tempTitle release];

    //tempQuery is leaking
    NSString *tempQuery = [[aDecoder decodeObjectForKey:@"QueryValue"] retain];
    self.query = tempQuery;
    [tempQuery release];
}
return self;
}

- (void)dealloc {
 [theTitle release];
 [query release];
 [super dealloc];
}

这也列为仪器泄漏

NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"savedQueries"];
if (dataRepresentingSavedArray != nil)
{

    //This is Leaking in Instruments
    NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
    if (oldSavedArray != nil) {

        //tempCustomQueryArray is also leaking
        NSMutableArray *tempCustomQueryArray = [[NSMutableArray alloc] initWithArray:oldSavedArray];
        if (savedQueries != nil) {
            savedQueries = nil;
        }
        self.savedQueries = tempCustomQueryArray;
        [tempCustomQueryArray release];
    }
 }

2 个答案:

答案 0 :(得分:2)

在此:

NSString *tempTitle = [[aDecoder decodeObjectForKey:@"QueryTitle"] retain];
self.theTitle = tempTitle;
[tempTitle release];

retainrelease不是必需的,因为您的属性将retain该对象。但是,我认为这两个字符串是红鲱鱼;泄漏可能是在其他地方。

我怀疑savedQueries未在dealloc中发布我认为未显示的内容。这会挂在查询和其他一些东西上。

这并不完全解释oldSavedArray的泄漏来自哪里(除非我遗漏了什么)。

启用分配工具中的保留/释放跟踪,并查看每个保留/释放的调用位置。你会在某个地方找到一个不平衡的人。

我写了一篇相关的blog post,可能会有帮助。

答案 1 :(得分:0)

我没有看到你在哪里实现了encodeWithCoder委托方法,或者你如何归档(保存到NSUserDefaults)。我也会尝试更改您的CustomQuery.m方法以反映:

- (void)encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:self.theTitle forKey:@"QueryTitle"];
    [encoder encodeObject:self.query forKey:@"QueryValue"];
}

- (id)initWithCoder:(NSCoder *)aDecoder {

    self = [super init];
    self.theTitle = [aDecoder decodeObjectForKey:@"QueryTitle"];
    self.query = [aDecoder decodeObjectForKey:@"QueryValue"];

    return self;
}