Question

I want to convert NSValue to NSNumber. What is wrong with this code?

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

It causes a crash on the last line. What could happen here?

Was it helpful?

Solution

Please read my comment above for further explanation.

To achieve what you want, simply init an NSString with your (char *) and then invoke NSString's intValue. - Assuming you know the type, if not look at the comments below -

Cheers

OTHER TIPS

As @ale0xB diagnosed in the comments above, NSNumber doesn't actually provide its own implementation of the -initWithBytes:objCType: method; so, when you invoke that selector, you're actually getting the implementation that comes from NSNumber's base class NSValue. There is no1 difference between [[NSNumber alloc] initWithBytes:foo objCType:bar] and [[NSValue alloc] initWithBytes:foo objCType:bar] — they both call the same method implementation, which releases the self it was given and returns a new object which is generally of type NSConcreteValue (an undocumented subclass of NSValue but not of NSNumber).

To be even clearer:

#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
}

However, categories to the rescue! Martin Häcker has written a category NSNumber(CreatingFromArbitraryTypes) which can be adapted to do what you want. See the public-domain source code here.2 The basic idea is to special-case every possible type-encoding:

  • if you're trying to encode an "i", then dispatch to -numberWithInt:;
  • if you're trying to encode an "f", then dispatch to -numberWithFloat:;

and so on. This is tedious; but once you've written the code once, you can use the category from then on and simply call [NSNumber numberWithValue:myNSValue].

(1 – More or less. There's no difference significant in this context, I'd say.)

(2 – That code has a couple of bugs, especially in later revisions. See my patch here.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top