Сбой при преобразовании 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 - В этом коде есть пара ошибок, особенно в последующих версиях. Смотрите мой патч здесь.)

Другие вопросы по тегам