ObjC:区分 NSValue 和 NSNumber

ObjC: differentiating between NSValue and NSNumber

我有一些代码可以用来接收未知类型的对象。它可以是 NSStringNSNumber、包裹在 NSValue 或其他 class:

中的标量
-(void) doSomethingWith:(id) value {
    if ( <test-for-NSValue> ) { 
        // Do something with a NSValue
    } else {
        // Do something else
    }
}

我需要确定 NSValue 中哪里有标量类型。

问题是识别 NSValue 包装标量与 NSNumber。由于 NSNumber 继承自 NSValue 并且两者都是 class 集群,所以我在整理它们时遇到了麻烦。

所以:

[value isKindOfClass:[NSValue class]] ... 将 NSNumbers 视为 NSValues。

[value isMemberOfClass:[NSValue class]] ...无法识别 NSValues 因为实例是具体的子类型。

有人知道怎么做吗?

怎么样:

-(void) doSomethingWith:(id) value {
    if ([value isKindOfClass:[NSValue class]] && ![value isKindOfClass:[NSNumber class]]) {
       // NSValue but not instance of NSNumber
    } else {
       ...
    }
}

首先我们需要了解iskindofClass和isMemberOfClass的区别

isKindOfClass

Returns a Boolean value that indicates whether the receiver is an instance of given class or an instance of any class that inherits from that class.

YES if the receiver is an instance of aClass or an instance of any class that inherits from aClass, otherwise NO.

isMemberOfClass

Returns a Boolean value that indicates whether the receiver is an instance of a given class.

YES if the receiver is an instance of aClass, otherwise NO.

那么很重要

NSValue

An NSValue object is a simple container for a single C or Objective-C data item. It can hold any of the scalar types such as int, float, and char, as well as pointers, structures, and object id references. Use this class to work with such data types in collections (such as NSArray and NSSet), key-value coding, and other APIs that require Objective-C objects. NSValue objects are always immutable.

NSNumber

NSNumber is a subclass of NSValue that offers a value as any C scalar (numeric) type. It defines a set of methods specifically for setting and accessing the value as a signed or unsigned char, short int, int, long int, long long int, float, or double or as a BOOL. (Note that number objects do not necessarily preserve the type they are created with.) It also defines a compare: method to determine the ordering of two NSNumber objects

if ([value isKindOfClass:[NSValue class]]) //It will return YES because NSNumber value subclass or inherits from NSValue
{
   ..........
}

if ([value isMemberOfClass:[NSValue class]])  //It will return NO because NSNumber value is not a member of the NSValue
{
   ......... 
}

Class objects may be compiler-created objects but they still support the concept of membership. Thus, you can use this method to verify that the receiver is a specific Class object.