Ed Marty
Ed Marty

Reputation: 39700

Objective C Naming Convention for an object that owns itself

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

Answers (1)

Nikolai Ruhe
Nikolai Ruhe

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

Related Questions