Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSNumber responds positively to mutableCopy?

Is this a bug or is there a subtle lesson here?

NSNumber *someNumber = @(1);
[someNumber respondsToSelector:@selector(mutableCopy)]; // returns YES (!)
[someNumber respondsToSelector:@selector(mutableCopyWithZone:)]; // returns NO

Apple LLVM 7.1 (iOS SDK 9.3)

like image 298
Ben Flynn Avatar asked Jan 04 '23 14:01

Ben Flynn


2 Answers

This is because NSObject itself implements -mutableCopy (for all objects, even those which do not conform to NSCopying or NSMutableCopying) by calling into -mutableCopyWithZone: (so that things implementing NSMutableCopying get to just implement -mutableCopyWithZone: without needing to repeat the implementation for -mutableCopy).

Everything that inherits from NSObject responds to -mutableCopy, but if you actually called it, it would crash because NSNumber doesn't respond to -mutableCopyWithZone:.

You can see this with

assert([NSObject instanceMethodForSelector:@selector(mutableCopy)] == [NSNumber instanceMethodForSelector:@selector(mutableCopy)])

bbum's analysis summarizes this pretty well — there are some subtle edge cases when doing these checks dynamically, because you may get answers you don't at all expect.

like image 173
Itai Ferber Avatar answered Feb 27 '23 17:02

Itai Ferber


That's odd. I wouldn't expect the class to implement -mutableCopy. May be fallout from the tagged pointer implementation (if so, then @(REALLYBIGNUMBERTHATISNEARMAX) would change the behavior).

The subtle lesson is that you can't really use respondsToSelector: for generic functionality tests. Nor can you use isKindOfClass:. There are many situations where it would fail (NSArray vs. NSMutableArray used to behave very strange-- may still-- when trying to use introspection to determine mutability, for example).

Introspection works well for explicitly declared situations like delegation or data sources. Places where there is an @protocol declaration that specifically defines some set of @optional methods.

like image 36
bbum Avatar answered Feb 27 '23 16:02

bbum