I'm getting the following warning by the ARC compiler:
"performSelector may cause a leak because its selector is unknown".
Here's what I'm doing:
[_controller performSelector:NSSelectorFromString(@"someMethod")];
Why do I get this warning? I understand the compiler can't check if the selector exists or not, but why would that cause a leak? And how can I change my code so that I don't get this warning anymore?
For posterity's sake, I've decided to throw my hat into the ring :)
Recently I've been seeing more and more restructuring away from the
target
/selector
paradigm, in favor of things such as protocols, blocks, etc. However, there is one drop-in replacement forperformSelector
that I've used a few times now:These seem to be a clean, ARC-safe, and nearly identical replacement for
performSelector
without having to much about withobjc_msgSend()
.Though, I have no idea if there is an analog available on iOS.
In the LLVM 3.0 compiler in Xcode 4.2 you can suppress the warning as follows:
If you're getting the error in several places, and want to use the C macro system to hide the pragmas, you can define a macro to make it easier to suppress the warning:
You can use the macro like this:
If you need the result of the performed message, you can do this:
Because you are using ARC you must be using iOS 4.0 or later. This means you could use blocks. If instead of remembering the selector to perform you instead took a block, ARC would be able to better track what is actually going on and you wouldn't have to run the risk of accidentally introducing a memory leak.
Here is an updated macro based on the answer given above. This one should allow you to wrap your code even with a return statement.
Matt Galloway's answer on this thread explains the why:
It seems that it is generally safe to suppress the warning if you are ignoring the return value. I'm not sure what the best practice is if you really need to get a retained object from performSelector -- other than "don't do that".
You could also use a protocol here. So, create a protocol like so:
In your class that needs to call your selector, you then have a @property.
When you need to call
@selector(doSomethingWithObject:)
in an instance of MyObject, do this: