Reputation: 6384
Say I have a class DoStuff, and that class has two methods, like so
- (NSMutableDictionary* returnToCaller) methodOne : (NSString* ) myString {
NSMutableDictionary* bundleOfJoy = [[NSMutableDictionary alloc] init];
if (myString) {
bundleOfJoy = [self methodTwo];
}
return bundleOfJoy;
}
- (NSMutableDictionary* returnToMethodOne) methodTwo {
NSMutableDictionary* anotherDictionary = [[NSMutableDictionary alloc] init];
[anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];
return anotherDictionary;
}
ok, so bear with me as my memory-management-fu is kind of weak. I can't release the two dictionaries manually created after the returns as the release command won't be called. I can't do it before the returns or I pass no values. My understanding then is the way to handle this is with an autorelease pool...
pool = [[NSAutoreleasePool alloc] init];
and init my objects as such
NSMutableDictionary* anotherDictionary = [[[NSMutableDictionary alloc] init] autorelease];
and then call
[pool drain];
so, if that is correct, where do I init pool? In awakeFromNib? And where do I call [pool drain]?
if this is incorrect could someone straighten me out (but please type slowly) : D
thanks
Upvotes: 1
Views: 746
Reputation: 57169
The autorelease pool will already be set up for you in most cases. Unless you are running code in a separate thread without using GCD you do not need to allocate and drain a pool. Even if you did put an autorelease pool in that method the object would be autoreleased too soon since you would have to drain within the same method. With that said to get an autoreleased object you can use either a convenience constructor or add autorelease
to your alloc/init
.
- (NSMutableDictionary* /*returnToMethodOne*/) methodTwo {
//Convenience constructor
NSMutableDictionary* anotherDictionary = [NSMutableDictionary dictionary];
//or
//NSMutableDictionary* anotherDictionary = [[[NSMutableDictionary alloc] init] autorelease];
[anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];
return anotherDictionary;
}
Upvotes: 2
Reputation: 534893
The best solution is to use ARC. Then you'll never have to worry about this again. :)
Even then, you need to understand what ARC is doing for you. The discussion in my iOS programming book applies equally to Mac OS X:
http://www.apeth.com/iOSBook/ch12.html#_memory_management
Upvotes: 2
Reputation: 13164
And you typically wouldn't create and drain the pool yourself, it is being done by the framework for you, so you just autorelease objects you want to released later.
Of course this way you cannot control the time, so in case you create a lot of temporary autoreleased objects in some part of your program, you can wrap this piece of code in pool create and drain:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
... create objects...
[pool drain];
But as I said, it is just an option for special cases.
Upvotes: 2
Reputation: 12979
You need to autorelease
the objects that you return. They will exist for your calling code to use but will be released at some arbitrary point later in time.
- (NSMutableDictionary* returnToMethodOne) methodTwo {
NSMutableDictionary* anotherDictionary = [[NSMutableDictionary alloc] init];
[anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];
return [anotherDictionary autorelease];
}
You should almost never need to use autorelease pools unless you're needing to ensure low memory usage while running loops that generate lots of objects.
Another way to achieve this functionality would be to create an autoreleased object for which you don't have to manage the memory (using a convenience constructor). For example:
- (NSMutableDictionary* returnToMethodOne) methodTwo {
NSMutableDictionary* anotherDictionary = [NSMutableDictionary dictionary]; // Creates an autoreleased NSMutableDictionary object.
[anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];
return anotherDictionary; // No `autorelease` call because it's not our memory to manage.
}
Upvotes: 1
Reputation: 726479
The system maintains an autorelease pool for you. It is created before your program is started, and drained regularly when the event loop gets control. In most situations, you do not need your own autorelease pool: just call autorelease
before returning your object, and you will be OK.
P.S. If you would like to learn about situations when you do need your own autorelease pool, Apple put together a nice guide for you.
Upvotes: 2
Reputation: 3485
There is an automatic NSAutoreleasePool in each thread and you don't have to create one instead you're creating a new thread.
Use [pool release]; instead of [pool drain] unless to have a memory leak.
For your code it's the responsibility of the method to release allocated object so add
return [bundleOfJoy autorelease];
return [anotherDictionary autorelease];
Upvotes: 2