First the warning occurs as the automatic memory management (ARC) needs to know the type and ownership of the result of a method call in order to determine how to manage any returned references to objects.
Using performSelector
with a variable selector value does not provide this information - selector values (of type SEL
) in Objective C do not carry type information. Without the type information the safe assumption is to do no memory management, but this might cause a leak, and so the warning.
In your case it seems you are expecting a selector with a return type of void
, and if nothing is being returned nothing can be leaked.
Your attempt to avoid this by getting a type function pointer to the method and calling that will work, except you made a mistake. The error "Bad receiver type 'SEL'" is referring to the method call [_responseSelector withObject:_myJsonData]
- a selector is not an object and you can't send it messages! What you appear to be trying to do is supply one argument (_myJsonData
) to the method pre-bound into the function pointer, and the other two arguments (_myTarget
, _mySelector
) at the point of call. Why you should want this is unclear (maybe you're a Haskell user?).
The solution is simple, don't try to pre-bind the argument:
IMP imp = [_myTarget methodForSelector:_mySelector];
void (*func)(id, SEL, NSMutableData *) = (void *)imp;
func(_myTarget, _mySelector, _myJsonData);
However there is a different approach possible: as you know you are returning nothing (void
) you can instruct the compiler to simply turn off the warning for the performSelector
call:
// avoid warning on performSelector - return is void so leak not possible
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
(void)[_myTarget performSelector:_mySelector withObject:_myJsonData];
#pragma clang diagnostic pop
HTH