Objective-C doesn't need to know the type of the receiver. At run-time, all objects are just id
, and everything is dynamically dispatched. So any message can be sent to any object, no matter its type. (At run-time, objects are free to decide what to do with messages they don't understand. The most common thing to do is raise an exception and crash, but there are many kinds of objects that can handle arbitrary messages that don't map directly to method calls.)
There is a couple of technical details, however, that complicate this.
The ABI (application binary interface) defines different mechanisms for returning certain primitive types. As long as the value is "a word-sized integer," then it doesn't matter (this includes things like NSInteger
and all pointers, which means by extension all objects). But on some processors, floats are returned in different registers than integers, and structs (like CGRect
) might be returned in a variety of ways depending on their size. In order to write the necessary assembly language, the compiler has to know what kind of return value it will be.
ARC has added additional wrinkles that require that the compiler know a more about the type of the parameters (specifically whether they're objects or primitives), and whether there are any memory-management attributes that have to be considered.
The compiler doesn't really care what "real" type test
is, as long as it can figure out the types and attributes of -count
. So when dealing with an id
value, it looks through every known selector it can see (i.e. every one defined in an included header or the current .m
). It's fine if there are many of them on different classes, as long as they all agree. But if it can't find the selector at all, or if some of the interfaces disagree, then it can't compile the line of code.
As lobstah notes, you likely have a type somewhere in your Swift code that has an @objc
method called count()
or an @objc
property named count
that returns something other than Int
(which maps to NSInteger
, and so match the usual signature of -count
). You'll need to fix that method, or you'll need to hide it from ObjC (for example, by adding @nonobjc
).
Or much better: get rid of the id
, and use its actual type. id
is generally a bad idea in Cocoa, and is especially a bad idea if you're calling methods on it, since the compiler can't check that the object will respond and you may crash.