Re: How to clone a mutable dictionary
Re: How to clone a mutable dictionary
- Subject: Re: How to clone a mutable dictionary
- From: Steve Cronin <email@hidden>
- Date: Fri, 24 Apr 2009 11:15:54 -0500
Graham;
THANK-YOU for this informative and "full-bodied" answer!
I want make sure I fully understand:
1) The "Easy Way" works only if there are no collection objects as
values in the "copied" dictionary (or other collection).
It seems to me that the "Hard Way" is ultimately necessary for "every
Cocoa programmer".
Given that, I am inclined to just implement the "Hard Way" and be done.
It just seems too much bother to try and figure out if any random
future item is qualified for the "Easy Way". (code obfuscation- to
what end?)
Is there a compelling counter-argument against this viewpoint?
2) By establishing a category on NSObject, one goal you accomplish is
making -deepCopy available to custom objects that are sub-classed
directly from NSObject. True? Are there other reasons why one would
want to implement for NSObject? Since there is nothing to iterate
over in NSObject is this a correct implementation for NSObject:
@implementation NSDictionary (DeepCopy)
- (NSObject *) deepCopy { return [[[self class] allocWithZone:[self
zone]] init]; }
@end
3) If -deepCopy is implemented as above on NSObject then when you
implement a -deepCopy on a collection it overrides the NSObject
version and all is well. Nothing special need be done (ie no need for
a separately named -deepArrayCopy).
4) The suite of collections include: array, dictionary, and set. (I'm
an NSSet fan!) The mutable flavors all inherit from these 3 base
types and the countedSet inherits from mutableSet. So implementing
the -deepCopy on NSObject, NSArray, NSDictionary, and NSSet should
provide a comprehensive solution . Do you agree?
5) Your allusion to semantics is calling attention to the fact that
the returned object is to be treated in the same way as any system-
vended object from a -copy or -alloc-int. The requestor has the
responsibility for releasing the returned object.
6) The code you show for the "Hard Way" returns a mutableDictionary
where the signature promises a NSDictionary. The mutable flavor is
useful for the construction during iteration but is there a reason
for returning something other than what was promised?
Again really good stuff! Thanks!
Steve
On Apr 24, 2009, at 3:49 AM, Graham Cox wrote:
On 24/04/2009, at 6:39 PM, Graham Cox wrote:
I'm sorry if this is something silly!
When a dictionary is copied, the objects it contains are not
copied, merely retained by the second dictionary. Likewise
setObject:forKey only retains the object.
You need to copy each object ("deep copy") as it is transferred to
the second dictionary.
i.e. id obj = [[newThing objectForKey:key] copy];
[newThing2 setObject:obj forKey:key];
[obj release];
Incidentally this makes a very useful basic category on
NSDictionary, one that every Cocoa programmer is likely to need
sooner or later. Here's mine:
#import "NSDictionary+DeepCopy.h"
// setting this to 1 is not equivalent to a recursive deep copy if
the items in the collection are also collections.
#define DO_IT_THE_EASY_WAY 0
@implementation NSDictionary (DeepCopy)
- (NSDictionary*) deepCopy
{
#if DO_IT_THE_EASY_WAY
return [[NSDictionary alloc] initWithDictionary:self copyItems:YES];
#else
NSMutableDictionary* copy;
NSEnumerator* iter = [self keyEnumerator];
id key, cobj;
copy = [[NSMutableDictionary alloc] init];
while(( key = [iter nextObject]))
{
cobj = [[self objectForKey:key] deepCopy];
[copy setObject:cobj forKey:key];
[cobj release];
}
return copy;
#endif
}
@end
Note that this implies that there exists a category for any object
that implements -deepCopy (I have similar for NSObject, NSArray,
etc) which thus ensures that the deep copy works no matter how
deeply the structures are nested (i.e. dictionaries in dictionaries
in dictionaries work). The use of initWithDiciotnary:copyItems: does
NOT ensure this, though it would be OK if you knew for sure that
your structure wasn't recursive.
I also use the same semantics for -deepCopy as for a normal -copy,
that is, the object returned has a retain count of 1 and isn't
autoreleased.
--Graham
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden