Hello,
how can i check a variable is NSArray or NSMutableArray???
Thanks
Hello,
how can i check a variable is NSArray or NSMutableArray???
Thanks
See NSObject's -class
method:
NSLog(@"myUnknownArray is of type: %@", [myUnknownArray class]);
You can also check more directly with the +class
method:
BOOL isMutableArray = [myUnknownArray isKindOfClass:[NSMutableArray class]];
You have to use:
[yourArray isKindOf: [NSArray class]]
since a simple comparization of the classes may fail because your array is probably not a NSArray but of some other low level type. You may also check if your array responds to the methods you need.
[yourArray respondsToSelector: @selector(addObject:)]
Consider:
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;
}
(I'm using non-empty arrays because an empty NSArray
is common enough that Cocoa offers a single shared instance as an optimization.)
array's class: NSCFArray
mutableArray's class: NSCFArray
array responds to addObject: YES
I.e. neither -isKindOfClass:
nor checking for implementation of addObject:
will work.
In short, you can't tell the difference between an NSArray and an NSMutableArray. This is by design and very much the intended behavior. It also holds true for NSString
, NSDictionary
and NSSet
(all of which have a mutable subclass).
That may come as a surprise. The reality, though, is that design patterns that require checking for mutability are confusing to use and incur significant overhead.
For example, if test-for-mutability were a common pattern than all of the methods in Cocoa that return NSArray
instances would have to actually return NSArray
instances and never return a reference to the internal NSMutableArray
that might be being used.
Bad but technically accurate advice...
The only way to do it is to invoke [unknownArray addObject:someObject]
inside a @try
/@catch
block and catch the NSInternalInconsistencyException
that will be thrown if unknownArray
is immutable (the actual exception could be a method not implemented or a class is immutable exception).
Good advice...
The short answer though is never try to peer inside an immutable object to see if it is internally mutable.
The reason peering at the mutability of immutable objects is prevented, is to support methods on classes that work like this:
- (NSArray *)internalObjects
{
return myInternalObjects;
}
the object myInternalObjects
could be mutable but this method on this class is saying: don't mutate what I return to you. There may be serious dangers with doing so. If the class allows you to change the array, it will have a different accessor or mutator method.
If you have a friend class that needs mutable access to the myInternalObjects variable, then declare a special adapter category that only the friend class imports with a method like
- (NSMutableArray *)mutableInternalObjectsArray;
This will allow the friend (which you are assuming is smart enough to not violate special rules) to have the access it needs but without exposing mutability in a broader sense.