Question

We are working in a way to make a fixed array (and all its fixed components, in several levels) mutable, and it seems that the only way to do it is iterate through all the levels in the nested fixed arrays and create mutable objects either using arrayWithArray or mutableCopy.

Doing some research I found that both NSArray and NSMutableArray return the same value (int 19) when the CFgetCFType() function is used.

Attached is the sample code

NSArray *array = @[@"one", @"two"];
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];
int id1 = CFGetTypeID((__bridge CFTypeRef)(array));
int id2 = CFGetTypeID((__bridge CFTypeRef)(mutableArray));
NSLog(@"Type: %i Type: %i", id1, id2);

Why is it, that both struct types return the same CFTypeID?. Does it mean that the mutability of NSMutableArray is hidden within the opaque definition of CFMutableArrayRef?

Was it helpful?

Solution

NSArray has a lot of extremely complicated and undocumented behaviour. It does some crazy stuff to improve real world performance.

The high level behaviour of NSArray and NSMutableArray is well documented but those two classes do not actually exist, instead you get instances of other classes, which class you actually get will depend on heuristic decisions the framework will make based on the actual data in the array and how you access it.

Creating copies of an array might not actually make a copy until you start modifying it. And even then, it may never make copies, it might keep the original array around and maintain a delta of changes that have been made.

If you need to know what is going on, then you should not be using NSArray at all. Instead you should drop to C arrays or perhaps even NSMutableData (tip: NSMutableData is awesome when the contents are potentially too big to fit in RAM).

The specific behaviour you are seeing could change at any time depending on the operating system version and perhaps even the hardware your app is executing on. Do not rely on how NSArray works in practice, because that is unpredictable. Instead rely on the documentation. Anything undocumented cannot be trusted, especially with NSArray which is a special case class.

Also, never ever subclass NSArray. Instead create a wrapper class that uses NSArray internally.

OTHER TIPS

I did some rough testing. It looks like the CFTypeID is the same for any array: big/small, static/runtime generated, and mutable/immutable. If I had to make a guess, I would guess that all classes in the NSArray/CFArrayRef cluster class group used the same CFTypeID.

It doesn't matter. That is an implementation detail on which you can't rely.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top