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

我怎样才能检查一个variables是一个NSArray或NSMutableArray?

*注意,NS {,Mutable}数组的实现在写这个答案之后已经改变了。 因此, isKindOfClass:现在可以工作。 何时何地平台,我不知道。

在logging为安全之前,我强烈build议不要编写试图检测集合是否可变或不可变的代码。 即使是安全的,这样的devise模式几乎总是performance出严重的devise缺陷。

(对于那些访问)提交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:实现addObject:将工作。

总之,你不能区分NSArray和NSMutableArray之间的区别。 这是devise和非常预期的行为。 它也适用于NSStringNSDictionaryNSSet (所有这些都有一个可变的子类)。

这可能是一个惊喜。 然而事实是,需要检查可变性的devise模式使用起来很混乱,并且会带来很大的开销。

例如,如果test-for-mutability比Cocoa中的所有方法都是常见模式,那么返回NSArray实例将不得不实际返回NSArray实例,并且永远不会返回可能正在使用的内部NSMutableArray的引用。

不好,但技术上准确的build议…

唯一的方法是在@try / @catch块内调用[unknownArray addObject:someObject]并捕获如果unknownArray不可变的情况下将抛出的unknownArray (实际的exception可能是未实现的方法,或者类是不可变的例外)。

好build议…

简短的回答虽然是从来不尝试在一个不可变的对象里面看看它是否是内部可变的。

阻止不可变对象的可变性的原因是为了支持像这样工作的类的方法:

 - (NSArray *)internalObjects { return myInternalObjects; } 

对象myInternalObjects可能是可变的,但是这个类的方法是这样说的:不要改变我返回给你的东西。 这样做可能会有严重的危险。 如果类允许你改变数组,它将有一个不同的访问器或增变器方法。

如果您有一个需要对myInternalObjectsvariables进行可变访问的朋友类,那么声明一个特殊的适配器类别,只有朋友类使用类似方法

 - (NSMutableArray *)mutableInternalObjectsArray; 

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

我会做以下事情 –

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

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

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

有很less的情况下,检查内部types是一个好主意(其他答案已经涵盖了这些)。 如果你想要一个可变数组,不要检查一个现有的数组是否是可变的,只要让你自己知道它是可变的。

请参阅NSObject的-class方法:

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

您还可以直接使用+class方法检查:

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

使用 …

[数组isKindOfClass:[NSMutableArray类]]

[数组isKindOfClass:[NSArray类]]

这将工作正常。

你必须使用:

 [yourArray isKindOf: [NSArray class]] 

因为类的简单比较可能失败,因为你的数组可能不是一个NSArray,而是一些其他的低级types。 你也可以检查你的数组是否响应你所需要的方法。

 [yourArray respondsToSelector: @selector(addObject:)]