Сбой при преобразовании NSValue в NSNumber
Я хочу конвертировать NSValue в NSNumber. Что не так с этим кодом?
char value[4];
[myNSValue getValue:(void*)value];
NSNumber *number = [[NSNumber alloc] initWithBytes:(void*)value objCType:[myNSValue objCType]];
NSTimeInterval duration = [number intValue];
Это вызывает сбой в последней строке. Что здесь может случиться?
2 ответа
Пожалуйста, прочитайте мой комментарий выше для дальнейшего объяснения.
Чтобы достичь того, что вы хотите, просто начните NSString с помощью вашего (char *), а затем вызовите intValue NSString. - Если вы знаете тип, если не посмотрите на комментарии ниже -
ура
Как @ale0xB диагностируется в комментариях выше, NSNumber
на самом деле не обеспечивает свою собственную реализацию -initWithBytes:objCType:
Способ; поэтому, когда вы вызываете этот селектор, вы на самом деле получаете реализацию, которая исходит от NSNumber
базовый класс NSValue
, Там нет 1 разницы между [[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
}
Тем не менее, категории на помощь! Мартин Хекер написал категорию NSNumber(CreatingFromArbitraryTypes)
который может быть адаптирован, чтобы делать то, что вы хотите. Посмотрите исходный код общественного достояния здесь. 2 Основная идея состоит в том, чтобы в каждом конкретном случае использовать кодировку:
- если вы пытаетесь закодировать
"i"
, а затем отправить в-numberWithInt:
; - если вы пытаетесь закодировать
"f"
, а затем отправить в-numberWithFloat:
;
и так далее. Это утомительно; но как только вы написали код один раз, вы можете использовать категорию с этого момента и просто вызвать [NSNumber numberWithValue:myNSValue]
,
(1 - Более или менее. В этом контексте, я бы сказал, нет существенных различий.)
(2 - В этом коде есть пара ошибок, особенно в последующих версиях. Смотрите мой патч здесь.)