An object can be released by sending it a -release
or -autorelease
message.
With -release
the reference count is immediately decremented which may lead to a deallocation.
With -autorelease
the decrement is deferred to keep an object alive beyond the scope in which it was created. For example, a helper method -createFoo
may return an autoreleased object so that callers can use the returned object without it being immediately deallocated on return from the method, and without having to worry about who is responsible for releasing it.
With ARC, the compiler handles all these details for you. All you need to know is that sometimes objects are kept alive a little longer using autorelease
.
This 'keeping alive' behaviour has implications for loops like the following:
- (void)foobar
{
for (/* a long time */) {
NSMutableString *s = [NSMutableString string];
// ...
}
}
The +string
method on NSMutableString
will return an autoreleased object. This is not automatically deallocated at the end of the loop iteration or method (well, ARC can do some clever optimizations by looking at the call stack, but we will ignore this). This means you will get unbounded memory growth while you are inside the loop body.
Note that if we had used the following:
NSMutableString *s = [[NSMutableString alloc] init];
then ARC would insert a release
call at the end of the loop body and the string would be immediately released.
To work around the unbounded memory growth of the first example, you define an explicit autorelease pool:
- (void)foobar
{
for (/* a long time */) {
@autoreleasepool {
NSMutableString *s = [NSMutableString string];
// ...
}
}
}
Now, after each iteration of the loop, the autorelease pool is destroyed and any objects that were autoreleased inside the pool (including our string) will be released immediately.
So it all depends on the kinds of methods you are calling and whether they are returning autoreleased objects.