Does NSMutableArray actually count elements every time the count method is called?

Due to cocoa design patterns, the instance method name of count in NSMutableArray ambiguous; it can either return the stored variable count , or count the elements in the array each time it is called, and return it (cocoa dictates that a method that simply returns the value of the variable foo be foo , not getFoo ). NSMutableArray C NSMutableArray really count elements every time the count method is called, or does it return the value of a precomputed variable? If it was Java, I would look at the source code, but I cannot find the source code for NSMutableArray . I looked at the API and all he said was this:

Returns the number of objects currently in the array.

Since there was no context, I canโ€™t say if this means that he does any calculations inside it or not.

+4
source share
2 answers

NSArray declares a private ivar _used , which appears to contain an array counter. Using object_getInstanceVariable() , you can verify that in the case of a particular subclass of __NSArrayM this variable increases and decreases when objects are added and deleted.

I used the following command line tool for the Mac OS X Foundation to verify this:

 #import <Foundation/Foundation.h> #import <objc/runtime.h> int main(int argc, const char * argv[]) { @autoreleasepool { NSMutableArray *anArray = [NSMutableArray array]; NSLog(@"anArray concrete class is %@", [anArray class]); UInt64 used = 0; for (NSString *toAdd in @[@"o", @"m", @"g"]) { object_getInstanceVariable(anArray, "_used", (void **)&used); NSLog(@"array = %@, used = %lld", anArray, used); [anArray addObject:toAdd]; } for (NSString *toRemove in [anArray copy]) { object_getInstanceVariable(anArray, "_used", (void **)&used); NSLog(@"array = %@, used = %lld", anArray, used); [anArray removeObject:toRemove]; } object_getInstanceVariable(anArray, "_used", (void **)&used); NSLog(@"array = %@, used = %lld", anArray, used); } return 0; } 

This program produced the following output:

 2013-01-31 17:40:15.376 Array[10173:303] anArray concrete class is __NSArrayM 2013-01-31 17:40:15.378 Array[10173:303] array = ( ), used = 0 2013-01-31 17:40:15.378 Array[10173:303] array = ( o ), used = 1 2013-01-31 17:40:15.379 Array[10173:303] array = ( o, m ), used = 2 2013-01-31 17:40:15.379 Array[10173:303] array = ( o, m, g ), used = 3 2013-01-31 17:40:15.380 Array[10173:303] array = ( m, g ), used = 2 2013-01-31 17:40:15.380 Array[10173:303] array = ( g ), used = 1 2013-01-31 17:40:15.380 Array[10173:303] array = ( ), used = 0 
+5
source

As you correctly noted, there is no guarantee that he will behave anyway.

In practice, however, -[NSArray count] is a constant-time operation. You can confirm this yourself by creating a small array and a large array and comparing the time taken to calculate them. It would be pretty stupid to have an O (n) count method in base array classes like this.

+7
source

All Articles