正如@ale0xB 在上面的评论中诊断的那样,NSNumber
实际上并没有提供自己的-initWithBytes:objCType:
方法实现;因此,当您调用该选择器时,您实际上得到了来自NSNumber
的基类的实现NSValue
。和之间没有任何区别——它们都调用相同的方法实现,释放它给出的并返回一个通常是类型的新对象(一个未记录的子类,但不是)。[[NSNumber alloc] initWithBytes:foo objCType:bar]
[[NSValue alloc] initWithBytes:foo objCType:bar]
self
NSConcreteValue
NSValue
NSNumber
更清楚的是:
#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。)