ObjectiveC - 释放作为参数添加的对象

时间:2011-01-12 20:09:56

标签: iphone objective-c memory-leaks memory-management

好的,这就是。

作为一名Java开发人员,我仍然在为ObjectiveC中的内存管理而苦苦挣扎。我已经掌握了所有基础知识,但有一段时间我遇到了挑战。

我想要做的是在Java中看起来像这样的东西:

MyObject myObject = new MyObject(new MyParameterObject());

MyObject类的构造函数采用了MyParameterObject类型的参数,我是即时启动的。

在ObjectiveC中,我尝试使用以下代码执行此操作:

MyObject *myObject = [[MyObject alloc] init:[[MyParameterObject alloc] init]];

但是,运行Build and Analyze工具会给我一个MyParameter对象的“潜在泄漏”警告,当我使用Instruments测试它时确实会发生这种情况。我确实理解为什么会发生这种情况,因为我使用alloc方法获取对象的所有权并且不放弃它,我只是不知道正确的方法。 我尝试使用

MyObject *myObject = [[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]];

然后分析工具告诉我“对象发送 - 自动发送太多次了”。

我可以通过将init MyParameterObject方法修改为return [self autorelease];来代替return self;来解决问题。分析仍然警告潜在的泄漏,但实际上并没有发生。但是我认为这种方法违反了在ObjectiveC中管理内存的惯例,我真的希望以正确的方式做到这一点。

提前完成。

4 个答案:

答案 0 :(得分:3)

好的,这是一个建议。

MyParameter *param = [[MyParam alloc] init];
MyObject *obj = [[MyObject alloc] initWithParam:param]; // do you know if param is retain'd or not?
[param release];

为什么这样?这是ObjC / Cocoa中使用的模式。您可以通过以下方式向NSArrays添加对象:

MyThing *thing = [[MyThing alloc] init];
[myMutableArray addObject: thing]; // this calls [thing retain]
[thing release];

您可能还想尝试这样做:

MyObject *obj = [[MyObject alloc] initWithParam: [MyParameter parameter]];

其中:

+ (id) parameter
{
    return [[[self alloc] init] autorelease];
}    

这样你就不用担心了。这与

相同
[NSData data];
[NSArray array];

我希望有所帮助。通常,在另一个方法调用(如setter或其他init)中使用init不是一个好主意。将它隐藏在类方法(+ (id) parameter)后面意味着用户知道它将是autorelease'd。

如果您不清楚retainrelease的内容有多少,您可以随时执行以下操作:


[编辑]

警告:显然你是should never use -retainCount。我发现教会学习者retain'内存管理的基础知识很有用,但重点很明显。

Never Use it in actual code or for performance testing.这仅用于了解retain的作用(我认为在这种情况下它的功能正常)。它永远不会为autoreleaseretainNSArray或其他基础/ AppKit / UIKit类的对象提供智能答案

MyParameter *param = [[MyParam alloc] init];
NSLog(@"param retain count: %d",[param retainCount]); // should be 1
MyObject *obj = [[MyObject alloc] initWithParam:param];
NSLog(@"param retain count: %d",[param retainCount]); // should be 2, if MyObject retains it.
[param release];
NSLog(@"param retain count: %d",[param retainCount]);  // should be 1

此外,当您dealloc MyObject时,如果您在初始化过程中release,则需要retain参数。

Apple推出的以下guide应该可以帮助您更好地理解Objective-C内存管理。

答案 1 :(得分:2)

MyThing *thing = [[MyThing alloc] init];
[otherThing methodWithAThing:thing];
[thing release];

或:

[otherThing methodWithAThing:[[[MyThing alloc] init] autorelease]];

或(如果您正在使用的课程中有“便利构造函数”):

[otherThing methodWithAThing:[MyThing thing]];

答案 2 :(得分:0)

MyObject *myObject = [[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]];

应该没问题,如果init中没有发布(在init中肯定没有发布)。我经常创建一个类方法,它创建一个自动释放的对象。所以代码是:

// using it:
MyObject *myObject = [[MyObject alloc] init:[MyParameterObject defaultParameters];

// in the class implementation of MyParameterObject
+ (MyParameterObject*) defaultParameters{
    MyParameterObject* out = [[MyParameterObject alloc] init];
    // set some values
    return [out autorelease];
}

答案 3 :(得分:0)

[[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]]

在不知道init方法发生了什么的情况下,这似乎很好。

但是,请注意,拼写这个“initWithParameterObject:”更加客观。尽管Obj-C的描述性方法名称实际上对代码可读性非常有用,但是他们禁止人们使用该语言。