views:

114

answers:

1

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?

+2  A: 

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.

Nikolai Ruhe
The above code is one example, but there are others which are more difficult to deal with. One, for example, sits around waiting for a UIButton to be clicked and releases itself after it's done handling the click. Since the UIButton doesn't retain targets, it has to retain itself. Any thoughts there?
Ed Marty
Accepted for partial answer; still looking for a better solution
Ed Marty