{"id":167,"date":"2008-11-14T20:11:17","date_gmt":"2008-11-15T01:11:17","guid":{"rendered":"http:\/\/vgable.com\/blog\/2008\/11\/14\/prefer-copy-over-retain\/"},"modified":"2009-11-10T19:30:00","modified_gmt":"2009-11-11T00:30:00","slug":"prefer-copy-over-retain","status":"publish","type":"post","link":"https:\/\/vgable.com\/blog\/2008\/11\/14\/prefer-copy-over-retain\/","title":{"rendered":"Prefer copy Over retain"},"content":{"rendered":"<p>(Almost) every time you use <code>retain<\/code> in Objective-C\/Cocoa, you really should be using <code>copy<\/code>.  Using <code>retain<\/code> can introduce some subtle bugs, and <code>copy<\/code> is faster then you think&#8230;<\/p>\n<h3>A Bug Waiting To Bite<\/h3>\n<p>The problem with using <code>retain<\/code> to &#8220;<a href=\"http:\/\/developer.apple.com\/documentation\/Cocoa\/Conceptual\/MemoryMgmt\/Tasks\/MemoryManagementRules.html\">take ownership<\/a>&#8221; of an object is that <strong>someone else has a pointer to the same object, and if they change it, you will be affected.<\/strong><\/p>\n<p>For example, let&#8217;s say you have a <code>Person<\/code> class with a straightforward setter method:<br \/>\n<code>- (void) setThingsToCallTheBossToHisFace:(NSArray*)newNames {<br \/>\n&nbsp;&nbsp;&nbsp;[thingsToCallTheBossToHisFace autorelease];<br \/>\n&nbsp;&nbsp;&nbsp;thingsToCallTheBossToHisFace = [newNames retain];<br \/>\n}<br \/><\/code><\/p>\n<p>And you use it to initialize a few <code>Person<\/code> objects:<\/p>\n<p><code>NSMutableArray *appropriateNames = [NSMutableArray arrayWithObject:@\"Mr. Smith\"];<br \/>\n[anIntern setThingsToCallTheBossToHisFace:appropriateNames];<\/p>\n<p>\/\/Salaried Employees can also be a bit more informal<br \/>\n[appropriateNames addObject:@\"Joe\"];<br \/>\n[aSalariedEmployee setThingsToCallTheBossToHisFace:appropriateNames];<\/p>\n<p>\/\/the wife can also use terms of endearment<br \/>\n[appropriateNames addObject:@\"Honey\"];<br \/>\n[appropriateNames addObject:@\"Darling\"];<br \/>\n[theBossesWife setThingsToCallTheBossToHisFace:appropriateNames];<br \/><\/code><br \/>\n<br \/>\nThe code looks good, it compiles without error, and it has a bug in it.  Because <code>setThingsToCallTheBossToHisFace:<\/code> uses <code>retain<\/code>, each <code>Person<\/code> object&#8217;s <code> thingsToCallTheBossToHisFace<\/code> field is actually pointing to the exact same <code>NSMutableArray<\/code>.  So adding &#8220;darling&#8221; to the list of names the wife can use also adds it to the intern&#8217;s vocabulary.<\/p>\n<p>If <code>copy<\/code> was used instead, then each <code>Person<\/code> would have their own separate list of names, insulated from changes to the temporary variable <code>appropriateNames<\/code>.<\/p>\n<h3>A Sneaky Bug Too<\/h3>\n<p>This is a particularly insidious problem in Foundation\/Cocoa, because mutable objects are subclasses of immutable objects.  This means every <code>NSMutableThing<\/code> is also a <code>NSThing<\/code>.  So even if a method is declared to take an immutable object, if someone passes in a mutable object by accident, there will be no compile-time or run-time warnings.<\/p>\n<p>Unfortunately, there isn&#8217;t a good way to enforce that a method takes an object, but not a subclass.  Because Foundation makes heavy use of <a href=\"http:\/\/developer.apple.com\/documentation\/Cocoa\/Conceptual\/CocoaFundamentals\/CocoaObjects\/chapter_3_section_9.html\">class clusters<\/a>, it&#8217;s very difficult to figure out if you have an immutable class, or it&#8217;s mutable subclass.  For example, with:<br \/>\n<code>NSArray *immutableArray = [NSArray array];<br \/>\nNSMutableArray *mutableArray = [NSMutableArray array];<br \/><\/code><\/p>\n<blockquote><p><code>[immutableArray isKindOfClass:[NSArray class]] is YES<br \/>\n[immutableArray isKindOfClass:[NSMutableArray class]] is YES<br \/>\n[mutableArray isKindOfClass:[NSArray class]] is YES<br \/>\n[mutableArray isKindOfClass:[NSMutableArray class]] is YES<br \/>\n[mutableArray isKindOfClass:[immutableArray class]] is YES<br \/>\n[immutableArray isKindOfClass:[mutableArray class]] is YES<br \/><\/code><\/p><\/blockquote>\n<p>Sad, but <code>true<\/code>.<\/p>\n<h3><code>copy<\/code> Is Fast!<\/h3>\n<p><strong>With nearly every immutable Foundation object, <code>copy<\/code> and <code>retain<\/code> are the same thing<\/strong> &#8212; there is absolutely <em>no<\/em> penalty for using <code>copy<\/code> over <code>retain<\/code>! The only time you would take a performance hit using <code>copy<\/code> would be if the object actually was mutable.  And then you really do want to <code>copy<\/code> it, to avoid bugs!<\/p>\n<p>The only exceptions I know of are: <code>NSDate<\/code>, and <code>NSAttributedString<\/code>.<\/p>\n<p>But don&#8217;t just take my word for it!  Here&#8217;s the snippet of code I used to test all this:<\/p>\n<p><code>NSMutableArray *objects = [NSMutableArray array];<br \/>\n\/\/add anything that can be made with alloc\/init<br \/>\nNSArray *classNames = [NSArray arrayWithObjects:@\"NSArray\", @\"NSColor\", @\"NSData\", @\"NSDictionary\", @\"NSSet\", @\"NSString\", nil];<br \/>\nfor(NSString *className in classNames) {<br \/>\n&nbsp;&nbsp;&nbsp;id obj = [[NSClassFromString(className) alloc] init];<br \/>\n&nbsp;&nbsp;&nbsp;if(obj)<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[objects addObject:obj];<br \/>\n&nbsp;&nbsp;&nbsp;else <br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSLog(@\"WARNING: Could not instatiate an object of class %@\", className);<br \/>\n}<\/p>\n<p>\/\/manually add objects that must be created in a unique way<br \/>\n[objects addObject:[[NSAttributedString alloc] initWithString:@\"\"]];<br \/>\n[objects addObject:[NSDate date]]; <br \/>\n[objects addObject:[NSNumber numberWithInt:0]];<br \/>\n[objects addObject:[NSValue valueWithSize:NSZeroSize]];<\/p>\n<p>\/\/test if retain and copy do the same thing<br \/>\nfor(id obj in objects)<br \/>\n&nbsp;&nbsp;&nbsp;if(obj != [obj copy])<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSLog(@\"copy and retain are not equvalent for %@ objects\", [obj className]);<br \/>\n<\/code><\/p>\n<h3>Best Practices<\/h3>\n<p>Get in the habit of using <code>copy<\/code>, anytime you need to <code>set<\/code> or <code>initWith<\/code> something.  In general, <code>copy<\/code> is safer then <code>retain<\/code>, so always prefer it.<\/p>\n<p>I believe it is best to try <code>copy<\/code> first.  If an object can not be copied, you will find out about it the <em>first<\/em> time your code is executed. It will be trivial to substitute <code>retain<\/code> for <code>copy<\/code>.  But it is much harder, and takes much longer, to discover that you should have been using <code>copy<\/code> instead of <code>retain<\/code>.  <\/p>\n<p>A program must be correct before it can be made to run faster.  And we have seen there is no performance penalty for <code>copy<\/code> on most common objects.  So it makes sense to try <code>copy<\/code> <em>first<\/em>, and then replace it with <code>retain<\/code> <em>if it proves to be necessary through measurement<\/em>. You will be measuring before you start &#8220;optimizing&#8221;, right?  (I also suspect that if taking ownership of an object is a bottle-neck, then the right optimization is not to switch to <code>retain<\/code>, but to find a way to use a mutable object, or an <a href=\"http:\/\/en.wikipedia.org\/wiki\/Object_pool\">object pool<\/a>, to avoid the &#8220;take ownership&#8221; step altogether.)<\/p>\n<p>Choose <code>copy<\/code>, unless you have a measurable justification for using <code>retain<\/code>.<\/p>\n<p>UPDATE 2009-11-10: <a href=\"http:\/\/cocoawithlove.com\/2009\/10\/how-blocks-are-implemented-and.html\">Obj-C 2.0 blocks have some peculiarities<\/a>, <\/p>\n<blockquote><p>For this reason, if you need to return a block from a function or method, you must <code>[[block copy] autorelease]<\/code> it, not simply <code>[[block retain] autorelease]<\/code> it.<\/p>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>(Almost) every time you use retain in Objective-C\/Cocoa, you really should be using copy. Using retain can introduce some subtle bugs, and copy is faster then you think&#8230; A Bug Waiting To Bite The problem with using retain to &#8220;take ownership&#8221; of an object is that someone else has a pointer to the same object, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,6,5,4],"tags":[241,156,224],"class_list":["post-167","post","type-post","status-publish","format-standard","hentry","category-bug-bite","category-cocoa","category-objective-c","category-programming","tag-best-practices","tag-foundation","tag-memory-management"],"_links":{"self":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/167","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/comments?post=167"}],"version-history":[{"count":2,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/167\/revisions"}],"predecessor-version":[{"id":494,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/167\/revisions\/494"}],"wp:attachment":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/media?parent=167"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/categories?post=167"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/tags?post=167"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}