We all love fancy data structures, but sometimes all you need is a nice NSMutableArray. Recently I was using an NSMutableArray filled with NSMutableArrays. Occasionally I needed to share this data with other classes, but I didn’t want to give them my mutable version, since they could change it out from under me. Really I just wanted to give them an immutable snapshot. But how to do this elegantly?

Imagine you have this mutable array:

NSMutableArray* masterArray =
    @[
        @[ @"Apples", @"Oranges" ].mutableCopy,
        @[ @"Yellow", @"Purple" ].mutableCopy
     ].mutableCopy;

How to make it immutable all the way down? You could just call good old copy:

NSArray* standardCopyArray = masterArray.copy;

Unfortunately that doesn’t work quite the way you want. It returns an immutable copy of the master array, but the sub-arrays are still the same mutable ones you started with.

So let’s do a little magic with key-value coding:

NSArray* copyKeyArray = [masterArray valueForKey:@"copy"];

This works, though you might be a little surprised at what it actually does. If you’ve never used it before, NSArray‘s valueForKey is incredibly useful. It creates a new array by calling valueForKey on each of it’s elements (I use this all the time). In this case, it ends up getting called recursively on each sub-array, so that they call copy on each of their elements (the leafs). That works in this case, but only because each sub-array only contains NSStrings, which support copy.

So what do you do if your arrays contain other objects, that don’t support copy?

NSArray* selfKeyArray = [masterArray valueForKey:@"self"];

This ends up working in nearly the same way, but when it bottoms out at the leafs, it just gets them via self instead of trying to copy them.

Easy peasy, and much more concise than looping through and copying each array.