Before ARC, I had an "X may not respond to xxx" warning, which is a pretty harmless warning which does not prevent it from compiling. Now, I am trying to convert my project to ARC, and I have an "No visible @interface for X declares the selector xxx" error, which prevents it from compiling.
I know exactly what I am doing, and why the warning was there, and I can tell you that the program is correct. Previously, the compiler compiled it with no problem, and should not now stop it from compiling.
It is true that class X's interface does not declare that selector, but X is a class that dynamically handles any message with any selector sent to it, using forwardInvocation:
(that is one of the beautiful things about Objective-C), so its interface cannot possibly declare all the selectors that can be called on it. And the selector is declared somewhere, just not on X.
I know exactly what I am doing, and why the warning was there, and I can tell you that the program is correct.
OK -- Just use objc_msgSend
et al. directly if you want to do the compiler's work.
It is true that class X's interface does not declare that selector, but X is a class that dynamically handles any message with any selector sent to it, using forwardInvocation: (that is one of the beautiful things about Objective-C), so its interface cannot possibly declare all the selectors that can be called on it. And the selector is declared somewhere, just not on X.
If it's too tedious to declare but not tedious enough to use in messaging that seems to contradict your program's use of the selector… Sounds like the dangerous territory of generated code with significant human intervention.
Perhaps you should consider declaring a protocol so the compiler can at least set the message calls up correctly for you -- and if you change or break something, it has a chance to adapt or notify you.
I'm not certain, but I believe under ARC it's more important that the compiler can see a method signature, because it needs to know what memory management is needed. So you'll either need to:
- Declare the methods you're using via one of the normal methods (i.e. ideally on the real receiver, but if nothing else as a category, even if only on
NSObject
).
- Do things manually via
NSInvocation
or some other similar means, taking full responsibility for memory management (which can be tricky, as you'll have to bridge to and from ARC).
Update: I just checked the clang source, and this is indeed the case - it needs the signature when using ARC. It's not just trying to be mean. :)
It is true that class X's interface does not declare that selector, but X is a class that dynamically handles any message with any selector sent to it, using forwardInvocation: (that is one of the beautiful things about Objective-C), so its interface cannot possibly declare all the selectors that can be called on it. And the selector is declared somewhere, just not on X.
Cast to id if you want to discard the static type information. Or if your object is a proxy for another class, maybe cast to that class.
So long as the method is declared somewhere in a header (which needed to be the case anyway), and there is no ambiguity with argument types, this should fix the error.
If you're interested in why this only is an issue with ARC enabled, check the answer to this question I asked: Why is 'no known method for selector x' a hard error under ARC?