Re: How to allocate and delegate; or how to keep GC and the static analyzer happy
Re: How to allocate and delegate; or how to keep GC and the static analyzer happy
- Subject: Re: How to allocate and delegate; or how to keep GC and the static analyzer happy
- From: Glen Low <email@hidden>
- Date: Sun, 11 Oct 2009 13:44:37 +0800
On 10/10/2009, at 12:29 PM, Jens Alfke wrote:
On Oct 8, 2009, at 7:33 PM, Glen Low wrote:
1. The code is not GC friendly as between the end of start and the
beginning of finishWithSomething, there are no references to the
object, so it may be collected.
There must be references to it; otherwise how would that object's
methods get called later on? Either it's a delegate of another
object (an NSURLConnection or NSTimer or whatever) or it starts a
new thread to run one of its methods. Either way, there are
references to the object that keep it alive.
2. The static analyzer in Xcode 3.2 doesn't like the construction,
thinking that the object is leaking from the start method.
I'm not sure what to do about that. Casting the result to (void)
might help, to explicitly state that you don't want to use the
result. (Does the static analyzer even work with GC? Stating that
the object is "leaking" only makes sense in a ref-counted
environment.)
It occurs to me that if I try to simulate the usual design pattern of
NSAlert, NSThread etc. callbacks that will keep the static analyzer
happy and probably be safer in the long run i.e.
- (void)start
{
Something* something = [[Something alloc] initWithDelegate:self];
[something doSomething];
[something release]; // #3
}
- (void)finishWithSomething:(Something*)something
{
[something release];
}
Note that the finishWithSomething: callback can happen after start has
finished.
So if Something uses e.g. an NSAlert
- (id)initWithDelegate:(id)delegate
{
if (self = [super init])
{
_alert = [[NSAlert alloc] init];
_alert.delegate = self;
_delegate = delegate;
}
return self;
}
- (void)doSomething
{
[self retain]; // #1
[_alert beginSheetModalForWindow:xxx modalDelegate:self
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
contextInfo:NULL];
}
- (void)alertDidEnd:(NSAlert*)alert returnCode:(int)returnCode
contextInfo:(void*)contextInfo
{
[_delegate finishWithSomething:self];
[self release]; // #2
}
Qn:
1. Are #1 and #2 strictly necessary? At the point of #1, the retain
count of something is just 1, since the alert doesn't retain its
delegate, and the release at #3 would have caused the object to be
dealloc'ed. Then the alert will end up messaging a zombie. Therefore
we need to add an extra retain and release around the callback.
2. In the presence of GC, #1 and #2 are no-ops. Does calling
beginSheetModalForWindow: with modalDelegate == self sufficient to
keep a reference alive to the something object? Or should I use
CFRetain and CFRelease instead (are the effects different here from -
retain and -release)?
Cheers, Glen Low
---
pixelglow software | simply brilliant stuff
www.pixelglow.com
aim: pixglen
twitter: pixelglow
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden