Okay, I have a feeling that you guys'll be able to quickly point out why I'm so confused about this, but I have a question as to why the following does NOT result in a compiler error or warning:
NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ];
selectedObject
is an NSObject
, and name
happens to be the name of a @property
of type int
.
What perplexes me is why the compiler is perfectly willing to assume that the return result of [ self.selectedObject valueForKey:name ]
is of type NSNumber *
(without typecasting it) in order to chain the message with a call to integerValue
.
Obviously, KVC wraps up non-object "number" types into NSNumber
, but there's no way for the compiler to know that -valueForKey:
will return an NSNumber *
in this particular case.
Why doesn't this result in a compiler warning along the lines of "id
may not respond to '-integerValue
'"?
I hope I got it right: This is because id
is “special”. Objects of the id
type can be sent any message you want, there is no checking done by the compiler and everything will be checked in runtime. Or, in other words, the id
type is the “dynamic typing” part of Objective-C, whereas all the other types (like NSObject
) are the “static typing” part.
This way you can choose where you want to use static typing, and where you want to use dynamic typing. It is perfectly legal to do something like this:
id str1 = @"Hello";
id str2 = [str1 stringByAppendingString:@", world"];
But usually you type the strings “tightly” as NSString
s, because you get the convenience of compile-time static type check, and only resort to dynamic typing where the static one would get in the way, like in the valueForKey
situation.
Time is passed and we have better type inference now thanks to the __auto_type
available since Xcode 8. So now you can do
#define let __auto_type const
#define var __auto_type
let a = @[@"pew pew"];
var b = 2;
b = a; //compiler warning "Incompatible pointer to integer conversion assigning to 'int' from 'NSArray *__strong const'"
and much more
In fact, I liked this so much so I made this as a pod for convenience.
pod 'SwiftyObjC'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With