Reputation: 6940
I know there was discussed a lot of times, but I'm confused in one point in studying memory management.
It says, that you have ownership of objects, you create with alloc/copy/new/mutableCopy or similar methods like allocWithSomething.
But, when you create object like NSArray *arr = [NSArray array];
in ARC, it is equivalent to write NSArray *arr = [[NSArray array]autorelease];
But, i see a lot of times statement like - you own EVERY object you create. But in the case above, we don't actually own object, we just add it to autorelease pool
. Therefore, we don't have to retain/release it, and it will be vanished as soon as it leave function scope (as Apple says, after an "event").
Can you please clarify that moment for me, do we really OWN EVERY object we create, or only objects with create with alloc/copy/mutableCopy/new, therefore increasing their retain count by +1?
Upvotes: 0
Views: 69
Reputation: 52530
You own every object that you create - as long as you wish to own it. "Owning" means that you hold a retain count to the object, and that you are going to release that retain count, or pass responsibility and the ownership to someone else.
[[NSArray alloc] init...]
creates an object that you own at that moment, with a retain count of 1. You may pass that object on to someone else who takes over the ownership.
[NSArray array]
creates and returns an object, but immediately adds it to an autorelease pool. The object isn't owned by anyone when it is returned; the autorelease pool just keeps it from being deallocated until the autorelease pool itself goes away. Anyone who wishes can take ownership of the object. And of course more than one bit of code can take ownership of the object. The object will go away when everyone releases ownership, and when the autorelease pool also goes away.
Anyway, ARC will take care of all these things for you.
Upvotes: 1
Reputation: 4436
This may be greatly oversimplified, but when you call [NSArray array], you are not actually requesting the memory space, the NSArray class is doing it for you. The NSArray class has a method that probably looks like:
+ (NSArray *) array
{
return [[[NSArray alloc] init] autorelease];
}
So it creates the object and "owns" it, not you.
For what it is worth, rather than "owning", I prefer to think of it as "responsible for". If you request memory for the object using alloc and similar methods, then you are responsible for releasing that memory.
Upvotes: 1
Reputation: 16774
This is a question of terminology of ownership in objective-C. The easiest rule would be we are owning the object if the object must be released after we are done with it. So to begin with an owner could be a class, could be a method or a function or even a block and still there are more. The same object may have multiple owners.
The release can be called via release
method or autorelease
method. We add it to the autorelease pool to delay its release until the pool is drained which in most cases in the end of the runloop. The code you posted is wrong with the [[NSArray array]autorelease];
as this would crash your app due to overreleasing. The correct version would be [[NSArray new] autorelease];
and this is more or less what the static method array
returns.
So if we exclude the autorelease
for now we have 3 elements: retain
will take the ownership of the object and increase the retain count also forcing you to release it at some point; release
will relinquish the ownership, decreasing the retain count and possibly deallocate the object if retain count drops to zero (the caller was the last owner); Object creation rule says all the methods or functions containing create, alloc, new, copy... will give you the ownership without retaining them and you are responsible to explicitly calling release on them.
When the object is created its retain count is 1. That means that every object on which we call alloc
+init
or any version of those will have a retain count of 1 and need to be explicitly released. All other static methods such as [NSArray array]
are nothing more but convenience to [[[NSArray alloc] init] autorelease]
and these need to be retained in order to take over the ownership.
So basically if you have a class that has an array pointer NSArray *_array
and we want to take the ownership we have to write _array = [someArray retain]
and in dealloc
method we have to write [_array release]
. If a method needs to take the ownership we need to call [someArray retain]
and when we are done with it we need to call [someArray release]
except when we return the object itself we need to call return [someArray autorelease]
. These are a very simple rules but some other cases make it extremely hard to track. So what the ARC does is it inserts these calls in the code for you and you do not need to worry about them. Still these same procedures exist as they did before the ARC.
So how exactly ARC inserts these calls is not really explained and differs from the versions. But if we take a look at the example you posted again but let us extend it:
- (NSArray *)foo // ARC version
{
NSArray *arr = [NSArray array];
for(NSObject *object in arr) NSLog(@"%@", object.description);
arr = [arr arrayByAddingObject:@"added something"];
return arr;
}
- (NSArray *)foo // ARC most likely behind the scenes
{
NSArray *arr = [[NSArray array] retain]; // reatin to claim ownership
for(NSObject *object in arr) NSLog(@"%@", object.description);
[arr autorelease]; // need to release it as it will be lost in the next line
arr = [[arr arrayByAddingObject:@"added something"] retain]; // the arr pointer now points to a different object. Claim the ownership of it
return [arr autorelease]; // need to relinquish the ownership
}
- (NSArray *)foo // standart non ARC wersion
{
NSArray *arr = [[NSArray alloc] init]; // we have the ownership by default
for(NSObject *object in arr) NSLog(@"%@", object.description);
NSArray *newArray = [[arr arrayByAddingObject:@"added something"] retain]; // need to explicitly retain this one as it is on the autorelease pool
[arr release]; // We do not need it anymore
return [newArray autorelease]; // need to relinquish the ownership
}
Upvotes: 1