Reputation: 418
Out of curiosity/excitement I have been reading whatever information I can find about ARC but I have one question I can't seem to find the answer to. Not sure if people can answer this due to NDAs or whatever, but I'll ask anyway. (There's plenty of information out there.......)
One thing ARC advertises is that you won't need to write dealloc methods anymore. Cool. But is this really true?
If I have a NSNetService or something, normally in my dealloc I would write
- (void)dealloc
{
[netService_ setDelegate:nil];
[netService_ stop];
[netService_ release];
[super dealloc];
}
Does ARC take care of that now? Or is not smart enough to know about stuff like that? If it isn't smart enough to know about that stuff (meaning I would still have to write custom deallocs in certain cases) would I have to release all ivars? Or just ones that wouldn't be simple releases?
- (void)dealloc
{
[netService_ setDelegate:nil]; // if these 3 lines are necessary...
[netService_ stop];
[netService_ release];
[myString_ release]; // would this one still be? or would ARC know to automagically add this
[super dealloc]; // seems this is forbidden in ARC
}
I guess my question really boils down to this: ARC says you won't have to write deallocs anymore in most cases; so when are the cases you do have to?
Upvotes: 4
Views: 1140
Reputation: 69777
It's clear that ARC wouldn't know about your [netService_ stop];
line. You'd have to include that yourself, since it's non-standard and does not have to do with retain
/release
.
Right after your dealloc
is run, ARC will release all strong
and weak
properties (and __strong
and __weak
iVars).
Here's some test code, just to see what happens:
@interface TestClass : NSObject
@property (nonatomic, strong) TestClass *anotherTestObject;
@end
@implementation TestClass
@synthesize anotherTestObject;
- (void)dealloc {
NSLog(@"I am deallocing %d", self.hash);
}
@end
And my test:
TestClass *thing1 = [[TestClass alloc] init];
NSLog(@"thing 1 %d", thing1.hash);
thing1.anotherTestObject = [[TestClass alloc] init];
NSLog(@"thing 2 %d", thing1.anotherTestObject.hash);
This will print out something like this
thing 1 1450176
thing 2 1459984
I am deallocing 1450176
I am deallocing 1459984
Since only one of the objects is getting autoreleased (thing1
) at the end of the test code, you can immediately tell that thing2
is getting released by someone else (since it's in a strong
property). However, if you overwrite setAnotherTestObject
you find that ARC is not setting it to nil
but rather just releasing it directly. You cannot override release
in ARC, otherwise I could demonstrate this too ;)
If I adjust the code and use weak
instead of strong
, the same behavior persists, but the output is different since the test case isn't holding onto the weak reference whatsoever.
Upvotes: 0
Reputation: 9926
As far as I understand it, you should think of ARC as just the static-analyzer built into the compiler, synthesizing retain and release calls where required (Which is also the reason why ARC code will be backwards-compliant with devices running iOS4).
So there is no way netService_
in your sample will be stopped automatically. You will need to write your own dealloc in this case.
The delegate issue is interesting, in iOS5 lingo it will be a weak property so it might be set to nil on dealloc... Not sure but it's interesting!
Another case you will have to take of yourself is you have handle objects which aren't objective-c objects, for example for Core Foundation objects you will need to write CFRetain
s and CFRelease
s yourself.
Upvotes: 4
Reputation: 16938
I think that if there is anything you need to do to cleanup an object, other than releasing it, is fair game for a custom dealloc method.
So in your own example with netService_
, the calls to setDelegate:
and stop
would be reasonable to call, but there'd be no need to call release
because ARC takes care of that.
Upvotes: 2