当前位置: 动力学知识库 > 问答 > 编程问答 >

Objective-C Properties and Memory Management

问题描述:

Given the following property definition:

@property (nonatomic,retain) MyObject* foo;

does the following code cause a memory leak:

self.foo = [[MyObject alloc] init];

?

It looks like the alloc call increments the retain count on the object to 1, then the retain inside the property setter increases it to 1. But since the initial count is never decremented to 0, the object will stick around even when self is released. Is that analysis correct?

If so, it looks like I have two alternatives:

self.foo = [[[MyObject alloc] init] autorelease];

which is not recommended on the iPhone for performance reasons, or:

MyObject* x = [[MyObject alloc] init];

self.foo = x

[x release];

which is a bit cumbersome. Are there other alternatives?

网友答案:

You are right, self.foo = [[MyObject alloc] init]; is leaking memory. Both alternatives are correct and can be used. Regarding the autorelease in such a statement: keep in mind that the object will released by the autorelease pool as soon as the current run loop ends, but it will most probably be retained a lot longer by self, so there is no issue with memory usage spikes here.

网友答案:

Are there any alternatives?

No.

You are not going to be able write much of an iPhone application without using autorelease and the Cocoa Touch library uses them in many places. Understand what it's doing (adding the pointer to a list for removal on the next frame) and avoid using it in tight loops.

You can use class method on MyObject that does alloc/init/autorelease for you to clean it up.

+ (MyObject *)object {
    return [[[MyObject alloc] init] autorelease];
}

self.foo = [MyObject object];
网友答案:

The easiest way to manage a retained property on the iPhone is the following (autorelease is not as bad as you think, at least for most uses):

-(id)init {
    if (self = [super init]) {
        self.someObject = [[[Object alloc] init] autorelease];
    }
    return self;
}

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

The autorelease releases the reference to the floating instance which is assigned to self.object which retains its own reference, leaving you with the one reference you need (someObject). Then when the class is destroyed the only remaining reference is released, destroying the object.

As described in another answer, you can also create one or more "constructor" messages to create and autorelease the objects with optional parameters.

+(Object)object;
+(Object)objectWithCount:(int)count;
+(Object)objectFromFile:(NSString *)path;

One could define these as:

// No need to release o if fails because its already autoreleased
+(Object)objectFromFile:(NSString *)path {
    Object *o = [[[Object alloc] init] autorelease];
    if (![o loadFromFile:path]) {
        return nil;
    }
    return o;
}
分享给朋友:
您可能感兴趣的文章:
随机阅读: