Reputation: 39700
With the latest releases of XCode that contain static analyzers, some of my objects are throwing getting analyzer issues reported. Specifically, I have an object that owns itself and is responsible for releasing itself, but should also be returned to the caller and possibly retained there manually.
If I have a method like + (Foo) newFoo
the analyzer sees the word New and reports an issue in the caller saying that newFoo
is expected to return an object with retain +1, and it isn't being released anywhere. If I name it + (Foo) getFoo
the analyzer reports an issue in that method, saying there's a potential leak because it's not deallocated before returning.
My class basically looks like this:
+ (Foo *) newFoo {
Foo *myFoo = [[[Foo new] retain] autorelease];
[myFoo performSelectorInBackground:@selector(bar) withObject:nil];
return myFoo;
}
- (void) bar {
//Do something that might take awhile
[self release];
}
The object owns itself and when its done, will release itself, but there's nowhere that it's being stored, so the static analyzer sees it as a leak somewhere. Is there some naming or coding convention to help?
Upvotes: 3
Views: 579
Reputation: 81878
In your implementation of newFoo
you create and return a Foo
instance with a logical retain count of +1. Cocoa Memory Management Rules require that methods prefixed with new
must return a retained object. But they also state that object ownership is passed to the calling method. That means, you cannot release the object on the background thread.
Let me propose a clearer and more Cocoa-ish way:
Rename newFoo
to something like fooInBackground
(where foo should be a verb). This new method returns an autoreleased instance, letting the thread doing it's own ownership. performSelectorInBackground:withObject:
retains both the receiver and the object argument, so there's no reason to retain it otherwise and manually release it in the background method.
+ (Foo *) fooInBackground {
Foo *myFoo = [[[Foo alloc] init] autorelease];
[myFoo performSelectorInBackground:@selector(bar) withObject:nil];
return myFoo;
}
Sidenote: Since you return the myFoo
object from fooInBackground
it would be a bug to just release instead of autoreleasing the object before returning it. The background thread could be finished before the first thread had a chance to retain myFoo
in the calling method. I'm just saying that because there seems to exist an (ill-founded) preoccupation against autorelease with all the new iPhone programmers coming to Cocoa.
Upvotes: 2