{"id":188,"date":"2008-12-20T22:55:25","date_gmt":"2008-12-21T03:55:25","guid":{"rendered":"http:\/\/vgable.com\/blog\/2008\/12\/20\/automatically-freeing-every-property\/"},"modified":"2009-11-29T18:24:53","modified_gmt":"2009-11-29T23:24:53","slug":"automatically-freeing-every-property","status":"publish","type":"post","link":"https:\/\/vgable.com\/blog\/2008\/12\/20\/automatically-freeing-every-property\/","title":{"rendered":"Automatically Freeing Every @property"},"content":{"rendered":"<p><a href=\"http:\/\/vgable.com\/code\/NSObject+CleanUpProperties.zip\">Here&#8217;s a category of <code>NSObject<\/code> that can simplify a <code>dealloc<\/code> method.<\/a>  It adds the method, <code>setEveryObjCObjectPropertyToNil<\/code>, that sets every property of the receiver to <code>nil<\/code>.  (Properties that are <code>readonly<\/code> or not an Objective-C object are ignored.)  This frees the underlying object, if the property is declared <code>copy<\/code> or <code>retain<\/code>; and it does no harm if it was declared <code>assign<\/code>.<\/p>\n<p>If every ivar (member variable) in your object has a property declared for it, then your <code>dealloc<\/code> method can often be replaced by this macro, or it&#8217;s two-line expansion:<br \/>\n<code><br \/>\n#define PROPERTY_ONLY_OBJECT_DEALLOC \\<br \/>\n- (void) dealloc { \\<br \/>\n&nbsp;&nbsp;&nbsp;[self setEveryObjCObjectPropertyToNil]; \\<br \/>\n&nbsp;&nbsp;&nbsp;[super dealloc]; \\<br \/>\n}<br \/>\n<\/code><\/p>\n<h3>Limitations<\/h3>\n<h4>Pointers<\/h4>\n<p>Any pointers (eg <code>char*<\/code>) will <em>not<\/em> be set to <code>NULL<\/code>; this includes pointers to an Objective-C object (eg <code>NSError** outError<\/code>).  Of course <code>NSObject* obj<\/code> <em>will<\/em> be set to <code>nil<\/code> since it is considered an Objective-C object, even though it is written as if it were a pointer.<\/p>\n<p>It is easy to build on <code>setEveryObjCObjectPropertyToNil<\/code> and have something that sets pointers to <code>NULL<\/code> as well.  But I felt it was too risky.  <a href=\"http:\/\/vgable.com\/blog\/2008\/05\/31\/messages-to-nowhere\/\">Sending a message to <code>nil<\/code> is valid<\/a>, but dereferencing a <code>NULL<\/code> pointer is a &#8220;bus error&#8221; crash. <code>[nil release];<\/code> does no harm, but <code>free(NULL);<\/code> is bad news. A settable <code>@property<\/code> that takes a raw pointer is a hybrid Objective-C, and &#8220;old&#8221;-C creature &#8212; I&#8217;ve never seen such a thing, so I&#8217;m wary of assuming that feeding it a <code>NULL<\/code> would be valid.  Plus, opening the door to pointers means dealing with <em>handles<\/em> (pointers-to-pointers) and their ilk.<\/p>\n<h4>ivars<\/h4>\n<p>Any ivars (member variables) with no settable <code>@property<\/code> declared on them will not be freed. You can inspect your own ivars like you can <code>@property<\/code>s (<a href=\"http:\/\/vgable.com\/blog\/2008\/12\/12\/catching-nil-member-variables\/\">example<\/a>), but it would <em>not<\/em> be safe to automatically <code>release<\/code> them. Some of them might be weak-links, meaning the object they point to was not sent a <code>retain<\/code> message.  Weak-links are not terribly rare, for example objects always have a weak link to their delegate.<\/p>\n<h3><a href=\"http:\/\/vgable.com\/code\/NSObject+CleanUpProperties.zip\">The Code<\/a><\/h3>\n<p>You will still need to <a href=\"http:\/\/vgable.com\/code\/NSObject+CleanUpProperties.zip\">download the source<\/a> to get helper functions like <code>SetterNameFromPropertyName()<\/code> for this to actually run, but this should give you an idea of how it works:<\/p>\n<p><code><br \/>\n@implementation NSObject(CleanUpProperties)<br \/>\n- (void) setEveryObjCObjectPropertyToNil;<br \/>\n{<br \/>\n&nbsp;&nbsp;&nbsp;unsigned int i, propertyCount = 0;<br \/>\n&nbsp;&nbsp;&nbsp;objc_property_t *propertyList = class_copyPropertyList([self class], &propertyCount);<br \/>\n&nbsp;&nbsp;&nbsp;if(propertyList){<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i = 0; i < propertyCount; i++){<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const char *propertyAttrs =  property_getAttributes(propertyList[i]);<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(PropertyIsObjCObject(propertyAttrs) && PropertyIsSettable(propertyAttrs)) {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSString *setterName = SetterNameFromAttributes(propertyAttrs);<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!setterName)<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setterName = SetterNameFromPropertyName(property_getName(propertyList[i]));<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[self performSelector:NSSelectorFromString(setterName) withObject:nil];<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(propertyList);<br \/>\n&nbsp;&nbsp;&nbsp;}<br \/>\n}<br \/>\n@end<br \/>\n<\/code><\/p>\n<p><a href=\"http:\/\/vgable.com\/code\/NSObject+CleanUpProperties.zip\"><\/p>\n<h3>Download The Code<\/h3>\n<p><\/a><br \/>\nAnd please let me know how it works for you.  I&#8217;ve started using <code>setEveryObjCObjectPropertyToNil<\/code> even if I only have one <code>@property<\/code>, because it means I&#8217;ll never forget to free one.<\/p>\n<h3>Warning (Update 2009-05-29)<\/h3>\n<p><a href=\"http:\/\/www.zathras.de\/angelweb\/blog-defensive-coding-in-objective-c.htm\">Uli Kusterer gives a good reason <em>not<\/em> to use this code<\/a>,<\/p>\n<blockquote>\n<h3>Don&#8217;t Use Accessors in Constructors or Destructors<\/h3>\n<p>This may sound a bit odd, but there is a reason to this madness. Constructors (i.e. <code>-init<\/code> methods in ObjC) and destructors (i.e. <code>-dealloc<\/code> or <code>-finalize<\/code>) are special methods: They are called before your object has fully been initialized, or may be called after it has already been partially torn down.<\/p>\n<p>If someone subclasses your class, your object is still an object of that subclass. So, by the time your <code>-dealloc<\/code> method is called, the subclass has already been asked to do its <code>-dealloc<\/code>, and most of the instance variables are gone. If you now call an accessor, and that accessor does anything more than change the instance variable (e.g. send out notifications to interested parties), it might pass a pointer to its half-destructed zombie self to those other objects, or make decisions based on half-valid object state. The same applies to the constructor, but of course in reverse.<\/p>\n<p>Now, some people that accessors should not be doing anything but change instance variables, but that is utter nonsense. If that was all they&#8217;re supposed to do, we wouldn&#8217;t need them. Accessors are supposed to maintain encapsulation. They&#8217;re supposed to insulate you from the internal details of how a particular object does its work, so you can easily revise the object to work in a completely different way, without anyone on the outside noticing. If an accessor could only change an instance variable, you would have very limited means to change this internal implementation.<\/p>\n<p>Moreover, I don&#8217;t think Apple would have introduced Key-Value-Coding and Key-Value-Observing if they didn&#8217;t agree at least partially that it&#8217;s fine to do a bunch of things in response to an accessor being used to mutate an object.\n<\/p><\/blockquote>\n<h3>Update 2009-11-29<\/h3>\n<blockquote><p>I&#8217;m amused at the prevalent &#8220;Apple knows best&#8221; attitude. Bindings, garbage collection, NSOperationQueue, and so many other things, Apple has gotten wrong and burned me in the process. I always trust my own evaluation over their recommendations.\n<\/p><\/blockquote>\n<p>&#8212;<a href=\"http:\/\/mikeash.com\/?page=pyblog\/friday-qa-2009-11-27-using-accessors-in-init-and-dealloc.html\">Mike Ash, <cite>Using Accessors in Init and Dealloc<\/cite><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here&#8217;s a category of NSObject that can simplify a dealloc method. It adds the method, setEveryObjCObjectPropertyToNil, that sets every property of the receiver to nil. (Properties that are readonly or not an Objective-C object are ignored.) This frees the underlying object, if the property is declared copy or retain; and it does no harm if [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,3,5,4,13],"tags":[224,263,264],"class_list":["post-188","post","type-post","status-publish","format-standard","hentry","category-cocoa","category-macosx","category-objective-c","category-programming","category-sample-code","tag-memory-management","tag-objective-c-20","tag-properties"],"_links":{"self":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/188","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=188"}],"version-history":[{"count":2,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/188\/revisions"}],"predecessor-version":[{"id":514,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/188\/revisions\/514"}],"wp:attachment":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/media?parent=188"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/categories?post=188"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/tags?post=188"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}