bbu*_*bum 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;
}
Run Code Online (Sandbox Code Playgroud)

(我使用的是非空数组,因为空的NSArray很常见,Cocoa提供了一个共享实例作为优化.)

array's class: NSCFArray
mutableArray's class: NSCFArray
array responds to addObject: YES
Run Code Online (Sandbox Code Playgroud)

即既不-isKindOfClass:检查也不会检查addObject:是否有效.

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

这可能会让人感到惊讶.但实际情况是,需要检查可变性的设计模式使用起来很混乱,并且会产生很大的开销.

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


Mat*_*her 6

不好但技术上准确的建议......

执行此操作的唯一方法是[unknownArray addObject:someObject]@try/ @catchblock 内部调用并捕获NSInternalInconsistencyException将在unknownArray不可变时抛出的内容(实际异常可能是未实现的方法或类是不可变的异常).

好建议...

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

隐藏不可变对象可变性的原因是支持类似于以下类的方法:

- (NSArray *)internalObjects
{
    return myInternalObjects;
}
Run Code Online (Sandbox Code Playgroud)

该对象myInternalObjects可以是可变的,但是这个类的方法是说:不要改变我给你的东西.这样做可能会有严重的危险.如果类允许您更改数组,则它将具有不同的访问器或更改器方法.

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

- (NSMutableArray *)mutableInternalObjectsArray;
Run Code Online (Sandbox Code Playgroud)

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


Nit*_*esh 5

我会做以下的事情-

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


Ale*_*lds 0

参见NSObject的-class方法:

NSLog(@"myUnknownArray is of type: %@", [myUnknownArray class]);
Run Code Online (Sandbox Code Playgroud)

您还可以通过以下方法更直接地检查+class

BOOL isMutableArray = [myUnknownArray isKindOfClass:[NSMutableArray class]];
Run Code Online (Sandbox Code Playgroud)

  • 或者,它在过去的版本中不起作用,但由于基金会的实现更改可能在某些当前版本中起作用。 (3认同)