正如@ale0xB 在上面的评论中诊断的那样,NSNumber 实际上并没有提供自己的-initWithBytes:objCType:方法实现;因此,当您调用该选择器时,您实际上得到了来自NSNumber的基类的实现NSValue。和之间没有任何区别——它们都调用相同的方法实现,释放它给出的并返回一个通常是类型的新对象(一个未记录的子类,但不是)。[[NSNumber alloc] initWithBytes:foo objCType:bar][[NSValue alloc] initWithBytes:foo objCType:bar]selfNSConcreteValueNSValueNSNumber
更清楚的是:
#import <assert.h>
#import <Foundation/Foundation.h>
int main()
{
id x;
x = [NSNumber numberWithInt:42];
assert( [x isKindOfClass:[NSNumber class]] );
assert( [x respondsToSelector:@selector(intValue)] );
int fortytwo = 42;
x = [[NSNumber alloc] initWithBytes:&fortytwo objCType:@encode(int)];
assert( [x isKindOfClass:[NSValue class]] );
assert( ! [x isKindOfClass:[NSNumber class]] ); // yikes!
assert( ! [x respondsToSelector:@selector(intValue)] ); // your particular problem
}
但是,类来救援!Martin Häcker 编写了一个类别NSNumber(CreatingFromArbitraryTypes),可以根据需要进行调整。在此处查看公共域源代码。2基本思想是对每种可能的类型编码进行特殊处理:
- 如果你想编码一个
"i", 然后派发到-numberWithInt:;
- 如果你想编码一个
"f", 然后派发到-numberWithFloat:;
等等。这很乏味;但是一旦您编写了一次代码,您就可以从那时起使用该类别并简单地调用[NSNumber numberWithValue:myNSValue].
(1 - 或多或少。我想说,在这种情况下没有显着差异。)
(2 - 该代码有几个错误,尤其是在以后的修订版中。请参阅我的补丁here。)