Jim is correct about -initWithArray:copyItems
sending a -copyWithZone:
message to each element. To get mutable copies of array elements, you'd need to send -mutableCopyWithZone:
(or just -mutableCopy
for brevity) to each element. This is fairly straightforward:
NSMutableArray *masterArray = ...
NSMutableArray *clone = [NSMutableArray arrayWithCapacity:[masterArray count]];
for (id anObject in masterArray)
[clone addObject:[anObject mutableCopy]]; // OR [clone addObject:anObject];
However, there is a deeper question hidden in your explanation of the problem: it seems you want both the array and its elements (dictionaries) to be mutable, but there are a few fine points that should be cleared up, especially in light of your stipulation that "[the] copy that is passed to other objects needs to be modified without modifying the original." Depending on exactly what you mean, this can be quite complex to guarantee and implement.
For example, suppose that the original array contains a number of mutable dictionaries. Creating mutable copies of these first two levels means that someone who obtains a copy can modify their own array and dictionaries in the array without changing the original array or dictionary directly. However, if a dictionary contains mutable objects (like an NSMutableArray, NSMutableString, etc.), the code using the "copy" could modify the contents of the dictionary indirectly, using only a reference to the mutable copy.
Mutable copies are "shallow", meaning only the first level is copied, and the copy has pointers to the same elements as the original structure. Thus, guaranteeing that there is no linkage between the original and the copy (at least, manually) would require a sweep through the entire structure and making copies. This can become more complicated if some elements don't conform to NSCopying or NSMutableCopying.
The easiest and fastest solution is to use the simple code above or just return a reference to the master array. This requires trusting that the client code will not modify the array, so this may not work in all situations, but if you control the calling code as well, this may be preferable. On the other hand, if you definitely want a totally separate copy, consider making use of NSCoding / keyed archiving:
NSMutableArray *masterArray = ...
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:masterArray];
NSMutableArray *clone = [NSKeyedUnarchiver unarchiveObjectWithData:data];
Basically, this converts everything into raw data bytes, then reconstitutes it into a new set of objects. For this to work, all the objects in the dictionary must conform to the NSCoding protocol. This can take a bit of doing, but it's an elegant generic way to guarantee object uniqueness. This certainly has a non-zero performance cost, but if you absolutely must guarantee there will be no side effects, it should work.