6

So I was playing with something where the class type of the arg is unknown until runtime. like this:

- (NSNumber *)doWhatever:(id)arg
{
    // this ALWAYS FAILS
    if ([arg isKindOfClass:[NSNumber class]]) {
        return arg;
    }
    else {
        // what was it???
        NSLog("arg klass=%@", [arg class]);  // prints NSCFNumber
    }

    // This check works correctly.
    if ([arg isKindOfClass:[NSArray class]]) {
        for (id x in arg) {
            NSNumber *result = [self doWhatever:x];
            if (result) {
                return result;
            }
        }
    }
    return nil;
}

- (void)someMethod
{
    NSArray *myArray = [NSArray arrayFromObjects:[NSNumber numberWithInt:3], nil]];
    NSNumber *myNum = [self doWhatever:myArray];
    NSLog(@"myNum=%@", myNum);
}

This is obviously a contrived example of what I'm trying to do. The point is this never works b/c the class of "arg" always appears as NSCFNumber, and I can't figure out a way to check for that.

Any way to make it less confusing to detect whether an arbitrary value in an array is an integer or not?


UPDATE: Thanks @chuck, @omz, and @Nikita Leonov for your help. What I posted here originally was just a simplification of the problem I was having and wrote it here without running it first. That code once updated to remove the errors (see below) runs fine actually.

The mistake I made in my real code that I was having trouble with was equally silly--I was passing the array back in to "doWhatever" instead of the item at array's index, which is why I was having problems.

Thanks for trying to help, however misguided my question was. Sorry for wasting everybody's time!

Corrected code that runs as desired:


- (NSNumber *)doWhatever:(id)arg
{
    // this NOW WORKS
    if ([arg isKindOfClass:[NSNumber class]]) {
        return arg;
    }
    else {
        // what was it???
        NSLog(@"arg klass=%@", [arg class]);  // prints NSCFNumber
    }
    
    // This check works correctly.
    if ([arg isKindOfClass:[NSArray class]]) {
        for (id x in arg) {
            NSNumber *result = [self doWhatever:x];
            if (result) {
                return result;
            }
        }
    }
    return nil;
}

- (void)someMethod
{
    NSArray *myArray = [NSArray arrayWithObjects:
                        [NSNumber numberWithInt:1],
                        [NSNumber numberWithInt:2],
                        [NSNumber numberWithInt:3],
                        [NSNumber numberWithInt:4],
                        nil];
    NSNumber *myNum = [self doWhatever:myArray];
    NSLog(@"myNum=%@", myNum);
}
peterh
  • 11,875
  • 18
  • 85
  • 108
jpswain
  • 14,642
  • 8
  • 58
  • 63
  • 1
    Are you sure that you build an array i such way? I wrote following code an isKindOfClass works well in this case: NSNumber *number = [NSNumber numberWithFloat:0.5]; if ([number isKindOfClass:[NSNumber class]]) { NSLog(@"NSNumebr"); } – Nikita Leonov Aug 08 '11 at 16:01
  • 1
    Checked initialization of array as shown in your "someMethod to os also works as expected for isKindOfClass call. – Nikita Leonov Aug 08 '11 at 16:04
  • 1
    Did you really use this exact code? There is no `arrayFromObjects:` method, it's called `arrayWithObjects:`. Except for that, it should work and print `NSCFArray` (or something similar) instead of `NSCFNumber`. – omz Aug 08 '11 at 16:10

1 Answers1

10

NSCFNumber is a subclass of NSNumber. As long as you're using isKindOfClass: rather than isMemberOfClass: or [arg class] == [NSNumber class], it should work. If not, your problem is elsewhere.

Chuck
  • 234,037
  • 30
  • 302
  • 389