6
votes

I have to perform a selector by name on a Class (not an instance) and use its return value:

id obj = [objClass performSelector:NSSelectorFromString(methodName) withObject:p1];

The selector creates a new instance of the Class. I need to use the returned instance. Obviously I get the usual performSelector may cause a leak because its selector is unknown warning since this project is compiled with ARC.

If I understand correctly (from the answers here and others), in this instance the performSelector will cause a leak (do correct me if I'm wrong, then I could just disable the warning and be done with it). The selectors are implemented as follows:

+ (id) objectWithFile:(NSString*)p1
{
    return [NSKeyedUnarchiver unarchiveObjectWithFile:p1];
}

What are my options when I have to use selector from string and the selector creates and returns a new instance of the object?

I considered NSInvocation but its getReturnValue method requires me to provide my own allocated buffer in which the return value is stored. I'm not sure if this even works with ARC and class methods, or whether I simply have to __bridge_transfer cast the malloc'ed return value buffer to id and that's all there is to it.

1
I don't yet understand why you would have a leak in your case. objectWithFile: returns an autoreleased object because it is not an alloc/copy/new method.Martin R
I'm not sure I understand this correctly. Say I return [Object new] instead of the unarchived object, that too returns an autorelease object but that would then leak? Or would the leak only occur if the performed selector itself calls alloc, new or copy?LearnCocos2D

1 Answers

5
votes

objectWithFile: is not a method of the "alloc, copy, init, mutableCopy, and new family" and therefore is a "Unretained return values" method in the sense of the "Clang/ARC documentation":

A method or function which returns a retainable object type but does not return a retained value must ensure that the object is still valid across the return boundary.
...
In the worst case, this may involve an autorelease, but callers must not assume that the value is actually in the autorelease pool.

So no matter what you do inside the method, the caller does not have to release the returned object.

Therefore I don't think that you have a memory leak in your code.