9

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.

user102008
  • 30,736
  • 10
  • 83
  • 104
  • The docs say: "To respond to methods that your object does not itself recognize, you must override methodSignatureForSelector:" Have you done that? – rdelmar Nov 21 '12 at 02:24
  • Maybe this answer could help you. http://stackoverflow.com/a/8002646/1341136 – hanjae Nov 21 '12 at 02:31
  • @rdelmar: No, this is a compile-time error. Nothing to do with how it works at runtime (which works fine) – user102008 Nov 21 '12 at 02:40
  • In some cases (which I've not quite figured out yet), simply casting the pointer to `id` will quiet the warning/error. (This is kind of necessary or pointers fetched from arrays or dictionaries would choke.) – Hot Licks May 21 '13 at 20:51

3 Answers3

5

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.

justin
  • 104,054
  • 14
  • 179
  • 226
2

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:

  1. 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).
  2. 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. :)

Nate
  • 31,017
  • 13
  • 83
  • 207
Wade Tregaskis
  • 1,996
  • 11
  • 15
1

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?

Community
  • 1
  • 1
Chris Devereux
  • 5,453
  • 1
  • 26
  • 32
  • This is not always possible. For example, if this is a message to `super`, it is not possible to "cast to id". – user102008 May 22 '13 at 04:05
  • Also, nowadays this may lead to the error msg "Multiple methods named '...' found with mismatched result, parameter type or attributes – Thomas Tempelmann Nov 26 '20 at 21:18