{"id":666,"date":"2010-08-15T22:09:40","date_gmt":"2010-08-16T03:09:40","guid":{"rendered":"http:\/\/vgable.com\/blog\/?p=666"},"modified":"2010-08-15T22:09:43","modified_gmt":"2010-08-16T03:09:43","slug":"my-uiviewcontroller-template","status":"publish","type":"post","link":"https:\/\/vgable.com\/blog\/2010\/08\/15\/my-uiviewcontroller-template\/","title":{"rendered":"My UIViewController Template"},"content":{"rendered":"<p>I haven&#8217;t formalized this as a proper Xcode template, but this is what&#8217;s in my <code>PrototypeViewController.m<\/code> file that I copy\/paste over the <code>UIViewController<\/code> subclasses Xcode makes.<\/p>\n<div class=\"code-box\">\n<pre>\n\n@interface MyViewController ()\n@end\n\n@implementation MyViewController\n- (void) releaseViewObjects;\n{\n\tif([[self superclass] instancesRespondToSelector:@selector(releaseViewObjects)])\n\t\t[(id)super releaseViewObjects];\n}\n\n- (void)viewDidUnload;\n{\n    [super viewDidUnload];\n    [self releaseViewObjects];\n}\n\n- (void)dealloc;\n{\n    [self releaseViewObjects];\n    [super dealloc];\n}\n\n@end\n<\/pre>\n<\/div>\n<p>Here are the reasons why, in no particular order:<\/p>\n<h3>Commented-Out Code is Evil<\/h3>\n<p>Littering source code with &#8220;comments&#8221; full of crufty, obsolete, or unimplemented code is not a good thing. <strong>Xcode&#8217;s default template is full of commented-out code<\/strong>. If you&#8217;re totally new to the platform, starting from the templates aren&#8217;t a bad way to learn.  But in my experiance, they do harm to a production code-base, by injecting hundreds of lines of commented-out code into a project.<\/p>\n<h3>Share code between <code>viewDidUnload<\/code> and <code>dealloc<\/code> With <code> releaseViewObjects <\/code><\/h3>\n<p>In my world, <code>releaseViewObjects<\/code> is <strong>solely responsible<\/strong> for cleaning up every <code>IBOutlet<\/code>, and any objects created in <code>viewDidLoad<\/code>.<\/p>\n<p>There are technical reasons why this is a little scary. Calling a method in <code>dealloc<\/code> is potentially risky, because the object may be in an invalid half-torn-down state, and because <a href=\"http:\/\/developer.apple.com\/mac\/library\/documentation\/Cocoa\/Conceptual\/KeyValueObserving\/KeyValueObserving.html\">Dark Runtime Magicks<\/a> could be afoot (see <a href=\"http:\/\/www.mikeash.com\/pyblog\/friday-qa-2009-11-27-using-accessors-in-init-and-dealloc.html\"><cite>Using Accessors in Init and Dealloc<\/cite><\/a>.)<\/p>\n<p>But in my experience, such bugs, although as scary as they sound, are rare corner-cases and still quite fixable. But <em>every<\/em> <code>UIViewController<\/code> needs to clean up after itself, so simplifying the universally common case is a net win.<\/p>\n<p>The <code>if([[self superclass] instancesRespondToSelector:@selector(releaseViewObjects)])<\/code> test wouldn&#8217;t be necessary if I added another class between <code>UIViewController<\/code> and my real code, so that I was sure my class&#8217; <code>super<\/code> implemented <code>releaseViewObjects<\/code>. But adding a subclass just to implement one empty method, to avoid a two-line test, isn&#8217;t worth it.<\/p>\n<p>The <code>(id)super<\/code> cast is intentional, to prevent compiler warnings.<\/p>\n<p>I have to use the more complex <code>[[self superclass] instancesRespondToSelector:<\/code> test, because <code>-[super respondsToSelector:]<\/code> <a href=\"http:\/\/www.cocoabuilder.com\/archive\/cocoa\/208788-super-respondstoselector.html\">doesn&#8217;t work<\/a>.<\/p>\n<h3>I Won&#8217;t <em>Really<\/em> Get To <code>didReceiveMemoryWarning<\/code><\/h3>\n<p>I&#8217;m not proud to admit this, but it&#8217;s true. We&#8217;ve all been told that a good iPhone program <em>must<\/em> release resources when it gets a memory warning, or else it will be killed. But in practice, there have always been better places to spend my time (or at least it sure feels that way!) Spending a few hours in Instruments to fix leaks prevents memory warnings in the first place, and that&#8217;s a bigger win.<\/p>\n<p>Besides, <strong>80% of what <code>didReceiveMemoryWarning<\/code> would do is handled in <code> releaseViewObjects<\/code><\/strong>, which is automatically called by the default implementation.<\/p>\n<p>So I break with Xcode and leave <code>didReceiveMemoryWarning<\/code> out of my template, because <em>the default class won&#8217;t use it<\/em>.<\/p>\n<h3>What About <code>init<\/code>?<\/h3>\n<p>I don&#8217;t have a default <code>init(With\u2026)<\/code> method. <strong>I try to use <code>autorelease<\/code>-ed objects everywhere I can<\/strong>, so I&#8217;m more comfortable implementing <code>+[MyViewController viewControllerForFoo:]<\/code>.<\/p>\n<p>But I don&#8217;t have a default constructor of <em>any<\/em> kind, because <strong>a constructor should take every value it <em>needs<\/em><\/strong>, and I don&#8217;t know what these values are until I&#8217;ve written a bit more of the class. It&#8217;s a chicken and egg problem.<\/p>\n<p>Once I&#8217;ve written out a bit more of the class, I&#8217;ll usually build something that looks like:<\/p>\n<div class=\"code-box\">\n<pre>\n+ (RouteMapViewController*) routeMapViewControllerWithWaypoints:(NSArray*)waypoints mapRegion:(MKCoordinateRegion)region;\n{\n\tRouteMapViewController *vc = [[[self class] new] autorelease];\n\tvc.title = NSLocalizedString(@\"The Path\",@\"\");\n\tvc.hidesBottomBarWhenPushed = YES;\n\tvc.waypoints = waypoints;\n\tvc.mapRegion = region;\n\treturn vc;\n}\n<\/pre>\n<\/div>\n<p>For what it&#8217;s worth I <a href=\"http:\/\/weblog.bignerdranch.com\/?p=56\">use this pattern to implement a 0-argument <code>-init<\/code><\/a>.<\/p>\n<h3>Empty Class Extension<\/h3>\n<p><a href=\"http:\/\/www.friday.com\/bbum\/2009\/09\/11\/class-extensions-explained\/\">Class extensions<\/a> are the best way to have &#8220;private&#8221; things in Objective-C. They let the compiler catch objects using another object&#8217;s private methods. They let a class have publicly <code>readonly<\/code>, but internally <code>readwrite<\/code>, properties.<\/p>\n<p>Bottom line: every nontrivial object I&#8217;ve written uses them, so they&#8217;re in my template.<\/p>\n<h3>Nothing Else (For Now)<\/h3>\n<p>My template is smaller than Xcode&#8217;s. That is by design. Outside of <a href=\"http:\/\/js1k.com\/\">esoteric contests<\/a>, having less code to maintain is a good thing. So <strong>I prefer a template that tries very hard to avoid adding code I don&#8217;t need.<\/strong><\/p>\n<p>Do you disagree with any of my choices? Please <strong>leave a comment explaining why<\/strong>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I haven&#8217;t formalized this as a proper Xcode template, but this is what&#8217;s in my PrototypeViewController.m file that I copy\/paste over the UIViewController subclasses Xcode makes. @interface MyViewController () @end @implementation MyViewController &#8211; (void) releaseViewObjects; { if([[self superclass] instancesRespondToSelector:@selector(releaseViewObjects)]) [(id)super releaseViewObjects]; } &#8211; (void)viewDidUnload; { [super viewDidUnload]; [self releaseViewObjects]; } &#8211; (void)dealloc; { [self releaseViewObjects]; [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[203,5,4,13],"tags":[241,609,610,134],"class_list":["post-666","post","type-post","status-publish","format-standard","hentry","category-iphone","category-objective-c","category-programming","category-sample-code","tag-best-practices","tag-template","tag-uiviewcontroller","tag-xcode"],"_links":{"self":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/666","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=666"}],"version-history":[{"count":1,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/666\/revisions"}],"predecessor-version":[{"id":667,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/666\/revisions\/667"}],"wp:attachment":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/media?parent=666"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/categories?post=666"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/tags?post=666"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}