0

我想将 NSValue 转换为 NSNumber。这段代码有什么问题?

char value[4];
[myNSValue getValue:(void*)value];
NSNumber *number = [[NSNumber alloc] initWithBytes:(void*)value objCType:[myNSValue objCType]];
NSTimeInterval duration = [number intValue];

它会导致最后一行崩溃。这里会发生什么?

4

2 回答 2

2

正如@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。)

于 2013-05-22T18:06:11.347 回答
1

请阅读我上面的评论以获得进一步的解释。

要实现你想要的,只需用你的 (char *) 初始化一个 NSString,然后调用 NSString 的 intValue。-假设你知道类型,如果不看下面的评论-

干杯

于 2012-09-25T15:21:50.467 回答