目标C:如何检查变量是NSArray还是NSM​​utableArray

时间:2009-11-24 08:33:59

标签: objective-c ios nsmutablearray nsarray

如何检查变量是NSArray还是NSM​​utableArray?

7 个答案:

答案 0 :(得分:32)

*请注意,自编写此答案以来,NS {,Mutable}数组的实现已发生变化。结果,isKindOfClass:现在有效。在什么平台上,何时何地,我不知道。

在记录为安全之前,我强烈建议强烈建议不要编写试图检测集合是否可变或不可变的代码。即使它是安全的,这种设计模式几乎总是表明存在严重的设计缺陷。

(对于那些有访问权限的人)提起rdar:// 10355515要求澄清。


考虑:

int main (int argc, const char * argv[]) {
    NSArray *array = [NSArray arrayWithObjects: [NSObject new], nil];
    NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects: [NSObject new], nil];

    NSLog(@"array's class: %@", NSStringFromClass([array class]));
    NSLog(@"mutableArray's class: %@", NSStringFromClass([mutableArray class]));

    NSLog(@"array responds to addObject: %@", 
          [array respondsToSelector: @selector(addObject:)] ? @"YES" : @"NO");

    return 0;
}

(我使用非空数组,因为空NSArray很常见,Cocoa提供单个共享实例作为优化。)

array's class: NSCFArray
mutableArray's class: NSCFArray
array responds to addObject: YES

即。 -isKindOfClass:和检查addObject:的实施都不起作用。

简而言之,您无法区分NSArray和NSMutableArray之间的区别。这是设计和非常预期的行为。它也适用于NSStringNSDictionaryNSSet(所有这些都有可变子类)。

这可能会让人感到惊讶。但实际情况是,需要检查可变性的设计模式令人困惑,并且会产生大量开销。

例如,如果test-for-mutability是一个常见的模式,而不是Cocoa中的所有方法,则返回NSArray个实例必须实际返回NSArray个实例,并且永远不会返回对内部的引用可能正在使用的NSMutableArray

答案 1 :(得分:6)

糟糕但技术上准确的建议......

唯一的方法是在[unknownArray addObject:someObject] / @try块内调用@catch并抓住NSInternalInconsistencyException,如果unknownArray- (NSArray *)internalObjects { return myInternalObjects; } 不可变的(实际的异常可能是未实现的方法或类是不可变的异常)。

好建议......

简短的回答是,永远不要试图在不可变对象内部查看它是否在内部是可变的。

防止不可变对象可变性的原因是支持类似这样工作的类的方法:

myInternalObjects

对象- (NSMutableArray *)mutableInternalObjectsArray; 可能是可变的,但是这个类的方法是说:不要改变我回到你身上的东西。这样做可能会有严重的危险。如果该类允许您更改数组,则它将具有不同的访问器或更改器方法。

如果你有一个需要对myInternalObjects变量进行可变访问的友元类,那么声明一个特殊的适配器类别,只有友元类使用类似

的方法导入
{{1}}

这将允许朋友(你假设它足够聪明,不违反特殊规则)获得它所需的访问权限,但不会在更广泛的意义上暴露可变性。

答案 2 :(得分:5)

我会做以下 -

if([unkownArray isKindOfClass:[NSMutableArray class]]){
  // This is a nsmutable array
}
else if ([unkownArray isKindOfClass:[NSArray class]]){
 // This is a nsarray
}

答案 3 :(得分:1)

如果你想要一个可变数组,请自己动手:

NSArray *someArray = /* obtain from somewhere, could be mutable, could be immutable */
NSMutableArray *mutableVersion = [someArray mutableCopy]; // definitely mutable

// later

[mutableVersion release];

在极少数情况下,检查内部类型是一个好主意(其他答案已经涵盖了那些)。如果你想要一个可变数组,不要检查一个现有的数组是否可变,只需自己创建,这样你就知道它是可变的。

答案 4 :(得分:0)

请参阅NSObject's -class方法:

NSLog(@"myUnknownArray is of type: %@", [myUnknownArray class]);

您还可以使用+class方法直接查看更多内容:

BOOL isMutableArray = [myUnknownArray isKindOfClass:[NSMutableArray class]];

答案 5 :(得分:0)

使用......

[Array isKindOfClass:[NSMutableArray class]]

[Array isKindOfClass:[NSArray class]]

这样可以正常工作。

答案 6 :(得分:-1)

你必须使用:

[yourArray isKindOf: [NSArray class]]

因为类的简单比较可能会失败,因为您的数组可能不是NSArray而是其他一些低级类型。您还可以检查阵列是否响应您需要的方法。

[yourArray respondsToSelector: @selector(addObject:)]