<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;D08FRXg5fSp7ImA9WxBbEkU.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800</id><updated>2010-03-10T21:36:54.625-08:00</updated><title>Cocoa with Love</title><subtitle type="html">Advanced programming tips, tricks and hacks for Mac development in C/Objective-C and Cocoa.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://cocoawithlove.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>114</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/CocoaWithLove" /><feedburner:info uri="cocoawithlove" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;D08FRXg4eip7ImA9WxBbEkU.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-1765857822214061232</id><published>2010-03-10T21:23:00.001-08:00</published><updated>2010-03-10T21:36:54.632-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-10T21:36:54.632-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="UIKit" /><category scheme="http://www.blogger.com/atom/ns#" term="object-oriented design" /><category scheme="http://www.blogger.com/atom/ns#" term="AppKit" /><title>Designing a view with Bindings (UITableView on the Mac)</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Bindings are one of the best ways of connecting your view and model on the Mac but due to the layers of abstraction involved &amp;mdash; and the fact that they don't exist on other platforms &amp;mdash; bindings can seem foreign and confusing. In this post, I'll show a complex view that is traditionally implemented without bindings (the iPhone's &lt;code&gt;UITableView&lt;/code&gt;) and show how it might be redesigned for the Mac with bindings.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;The aim&lt;/h4&gt;

&lt;p&gt;I'm going to show the design of &lt;code&gt;ColumnView&lt;/code&gt;, a Mac &lt;code&gt;NSView&lt;/code&gt; subclass which operates in a similar manner to the iPhone's &lt;code&gt;UITableView&lt;/code&gt;.&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/S5glOno3L4I/AAAAAAAAAmE/uQOxvYEc9g8/columnview.png?imgmax=800" alt="columnview.png" border="0" width="216" height="264" /&gt;

&lt;p&gt;Specifically, the &lt;code&gt;ColumnView&lt;/code&gt; will lay out &lt;code&gt;RowView&lt;/code&gt;s (a proper &lt;code&gt;NSView&lt;/code&gt; subclass instead of cells like &lt;code&gt;NSTableView&lt;/code&gt; arranges). The rows are grouped in sections (sections may have a header and may be independently sorted). The rows can have different heights and be different classes.&lt;/p&gt;

&lt;p&gt;I'm not aiming to make this a fully-fledged &lt;code&gt;UITableView&lt;/code&gt; recreation &amp;mdash; it won't support significant interactivity, animation or editing modes, although all these things could be added to the design (it is designed to be a flexible foundation, even if all features aren't present).&lt;/p&gt;

&lt;p&gt;The aim of this design is to show that the entire structure and configuration of the &lt;code&gt;ColumnView&lt;/code&gt; can be done with one binding. The &lt;code&gt;UITableViewDataSource&lt;/code&gt;/&lt;code&gt;UITableViewDelegate&lt;/code&gt;, normally required for a &lt;code&gt;UITableView&lt;/code&gt;, can all be replaced by this single binding.&lt;/p&gt;

&lt;p&gt;I won't be looking at bindings in Interface Builder in this post. I realize that is how most people configure bindings but to keep the number of topics down, I'm going to limit discussion to bindings configured in code.&lt;/p&gt;

&lt;h4&gt;Background: controller heavy implementations&lt;/h4&gt;

&lt;p&gt;Traditionally, Model-View-Controller would work like this:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Model&lt;/strong&gt; &amp;mdash; sends notifications when it changes but otherwise keeps to itself&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Controller&lt;/strong&gt; &amp;mdash; receives model notifications and actively changes views in response&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;View&lt;/strong&gt; &amp;mdash; passive and simply shows information the controller shoves at it&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;This works well but the controller ends up being huge because it contains all the logic of responding to changes, configuring the view, plus all of the interactivity work that may be required by the views.&lt;/p&gt;

&lt;p&gt;A number of larger views, including the iPhone's UITableView and the Mac's NSTableView (without bindings) operate on a delegate model which breaks the controller up slightly:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Model&lt;/strong&gt; &amp;mdash; (as before) sends notifications when it changes but otherwise keeps to itself&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Controller&lt;/strong&gt; &amp;mdash; pushes new data to the delegate and notifies the view that it needs an update&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;View&lt;/strong&gt; &amp;mdash; determines areas needing an update and asks the delegate how to display those areas&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;View delegate&lt;/strong&gt; &amp;mdash; tells the view how to update based on data from the controller&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;A view delegate is really just a controller but since it is invoked by the view, it allows the view to control when data is loaded and changes are made (the view can control lazy load order).&lt;/p&gt;

&lt;p&gt;Ultimately though, this second case can still involve a lot of code to configure the view and provide it with data. The potential advantage of breaking the controller into two pieces (the controller and the view delegate) is normally lost since both are frequently implemented in the same class.&lt;/p&gt;

&lt;h4&gt;Bindings: a reusable controller&lt;/h4&gt;

&lt;p&gt;The controller heavy nature of the above approaches can be burdensome as you need to rewrite the controller every single time &amp;mdash; it is entirely specific to the mode and view that it joins.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/CocoaBindings/CocoaBindings.html"&gt;Cocoa Bindings&lt;/a&gt; are a way of eliminating implementation specific controller code &amp;mdash; the entire controller layer can be handled with reusable controllers and observations and configurations specified in data, not code.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Cocoa Bindings purpose in one sentence&lt;/strong&gt;: If you can simplify your design so that all a controller needs to do is copy data from the model to the view, then the controller's role can be replaced by a simple, reusable "binding" object and all that remains is to configure that binding object with data.&lt;/blockquote&gt;

&lt;p&gt;The bindings structure is then:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Model&lt;/strong&gt; &amp;mdash; (as before) sends notifications when it changes but otherwise keeps to itself&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;KVO interface/controller&lt;/strong&gt; &amp;mdash; the interface that the model exposes must be Key Value Observing compliant. This interface may be part of the Model, or it can be a lightweight wrapper around the model, or a generic controller like NSArrayController.&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;&lt;strong&gt;Key Value Binding&lt;/strong&gt; &amp;mdash; ensures that data from the KVO controller is pushed to an object with exposed bindings. May pass the data through an NSValueTransformer before pushing to the exposed binding. A binding may also contain an options dictionary which tells the view how to handle data it receives.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;View&lt;/strong&gt; &amp;mdash; determines areas needing an update and asks the delegate how to display those areas
&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Exposed binding&lt;/strong&gt; &amp;mdash; any Key Value Coding compliant property on the view but may also have options and other metadata to support Interface Builder and configuration.&lt;/li&gt;&lt;/ul&gt;
&lt;/ol&gt;

&lt;p&gt;While I've included more layers in this description, most of the time, you'll only deal with two: the model and the view.&lt;/p&gt;

&lt;p&gt;The "Key Value Binding" layer is entirely automatic &amp;mdash; in fact, unless you're hacking or looking closely at the stack, you won't actually see the classes that handle this layer. It will "just happen".&lt;/p&gt;

&lt;p&gt;The "KVO interface/controller" and "Exposed binding" may or may not be automatic. Many model classes will be KVO compatible already, although others may require a shallow layer to improve their compatibility.&lt;/p&gt;

&lt;p&gt;The real work for bindings, is in designing views to be fully configurable through bindings alone.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Terminology&lt;/strong&gt;: I've already mentioned KVC and KVO. These technologies are fundamental to how bindings work. If you don't have great familiarity with these terms, you can read the Apple programming guide to &lt;a href="http://developer.apple.com/mac/library/documentation/cocoa/conceptual/KeyValueCoding/KeyValueCoding.html"&gt;Key Value Coding&lt;/a&gt; and &lt;a href="http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/KeyValueObserving/index.html"&gt;Key Value Observing&lt;/a&gt;. You could also read my earlier post on &lt;a href="http://cocoawithlove.com/2010/01/5-key-value-coding-approaches-in-cocoa.html"&gt;5 key-value coding approaches in Cocoa&lt;/a&gt; but note that bindings require proper &lt;code&gt;NSKeyValueCoding&lt;/code&gt; compatible KVC.&lt;/blockquote&gt;

&lt;h4&gt;Implicit bindings support&lt;/h4&gt;

&lt;p&gt;In some situations, you might be able to connect a model and view with a binding with no cooperation from either the model or the view. This will be the case if your model is already KVO compliant and your view can be totally configured by piping this KVO data directly into KVC properties on the view.&lt;/p&gt;

&lt;p&gt;For example, if your model has a &lt;code&gt;text&lt;/code&gt; property that is only ever changed through its &lt;code&gt;setText:&lt;/code&gt; method and you want to display that property in a text field, you can connect the two with:&lt;/p&gt;

&lt;pre&gt;[someTextField bind:@"stringValue" toObject:myModelObject withKeyPath:@"text" options:nil];&lt;/pre&gt;

&lt;p&gt;Bindings will do the rest.&lt;/p&gt;

&lt;p&gt;As soon as the binding is established, the binding will set the &lt;code&gt;stringValue&lt;/code&gt; property of the &lt;code&gt;someTextField&lt;/code&gt; to the value of the &lt;code&gt;text&lt;/code&gt; property from the &lt;code&gt;myModelObject&lt;/code&gt;. Every time the &lt;code&gt;text&lt;/code&gt; is set using the &lt;code&gt;setText:&lt;/code&gt; method, an automatic Key Value Observing notification will be detected by the binding and it will keep the text field in sync.&lt;/p&gt;

&lt;p&gt;Normally though, bindings are used in situations where the view explicitly supports them. For example, with &lt;code&gt;NSTextField&lt;/code&gt;, you would normally use &lt;code&gt;NSValueBinding&lt;/code&gt; instead of &lt;code&gt;@"stringValue"&lt;/code&gt;. Ultimately, the &lt;code&gt;NSTextField&lt;/code&gt; will map &lt;code&gt;NSValueBinding&lt;/code&gt; onto the same &lt;code&gt;@"stringValue"&lt;/code&gt; property but the supported binding guarantees compliance (and also supports other options like implicit conversion from &lt;code&gt;NSNumber&lt;/code&gt; to &lt;code&gt;NSString&lt;/code&gt;).&lt;/p&gt;

&lt;h4&gt;Adapting a delegate/dataSource view for use with bindings&lt;/h4&gt;

&lt;p&gt;Most views require a redesign so that they can be completely configured through Key Value Coding compliant properties. The reason for this is that the view must be completely configurable through KVC compliant properties to work with bindings.&lt;/p&gt;

&lt;p&gt;In adapting &lt;code&gt;UITableView&lt;/code&gt; for the Mac, I'll need to make such a redesign since &lt;code&gt;UITableView&lt;/code&gt; does not expose the KVC properties we would require.&lt;/p&gt;

&lt;h5&gt;Looking at the situation before bindings&lt;/h5&gt;

&lt;p&gt;To achieve the features I want, a &lt;code&gt;UITableView&lt;/code&gt; would require its &lt;code&gt;dataSource&lt;/code&gt; to implement the following methods:&lt;/p&gt;

&lt;pre&gt;– tableView:cellForRowAtIndexPath:
– numberOfSectionsInTableView:
– tableView:numberOfRowsInSection:
– tableView:titleForHeaderInSection:&lt;/pre&gt;

&lt;p&gt;and the &lt;code&gt;delegate&lt;/code&gt; would need to implement:&lt;/p&gt;

&lt;pre&gt;– tableView:heightForRowAtIndexPath:
– tableView:viewForHeaderInSection:&lt;/pre&gt;

&lt;p&gt;None of these methods set KVC properties so they all need to go.&lt;/p&gt;

&lt;h5&gt;Recategorizing delegate and controller methods as properties&lt;/h5&gt;

&lt;p&gt;We need to rethink what the table displays as data that we can set.&lt;/p&gt;

&lt;p&gt;Ultimately, a &lt;code&gt;UITableView&lt;/code&gt; contains two tiers of data: the section and the row. For each of the &lt;code&gt;UITableView&lt;/code&gt; &lt;code&gt;dataSource&lt;/code&gt; and &lt;code&gt;delegate&lt;/code&gt; methods, we can consider the returned value as either a property of a section, row (or the array containing them).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tableView:cellForRowAtIndexPath:&lt;/code&gt; &amp;mdash; Row property&lt;/li&gt;
&lt;li&gt;&lt;code&gt;numberOfSectionsInTableView:&lt;/code&gt; &amp;mdash; Property of the sections array&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tableView:numberOfRowsInSection:&lt;/code&gt; &amp;mdash; Property of the rows array within a section&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tableView:titleForHeaderInSection:&lt;/code&gt; &amp;mdash; Section property&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tableView:heightForRowAtIndexPath:&lt;/code&gt; &amp;mdash; Row property&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tableView:viewForHeaderInSection:&lt;/code&gt; &amp;mdash; Section property&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;ColumnView, ColumnSection and RowView binding interfaces&lt;/h4&gt;

&lt;h5&gt;Structure of data used for the bindings&lt;/h5&gt;

&lt;p&gt;The bindings design for the &lt;code&gt;ColumnView&lt;/code&gt; then comes directly from this categorization.&lt;/p&gt;

&lt;p&gt;At the top level we need to bind the &lt;code&gt;ColumnView&lt;/code&gt; to an array of sections. Each section must have a row array property.&lt;/p&gt;

&lt;p&gt;Each "section" is not an object of any specific class &amp;mdash; it can be any object from your model. To make it work, the &lt;code&gt;ColumnView&lt;/code&gt; must also know the key path from the section to its content. This key path can be set by using a binding option when a binding is established for the &lt;code&gt;sectionsArray&lt;/code&gt;. It is this type of key path traversal that allows the view to traverse model data whose structure it doesn't necessarily know.&lt;/p&gt;

&lt;p&gt;The only tricky point is the &lt;code&gt;tableView:cellForRowAtIndexPath:&lt;/code&gt; method. While the "&lt;code&gt;cellForRowAtIndexPath&lt;/code&gt;" could be considered a property, the rows and sections here a model objects and having "view" properties on model objects is a bad idea.&lt;/p&gt;

&lt;p&gt;I've opted instead to use the row's class as the property instead of a fully realized view. The &lt;code&gt;ColumnView&lt;/code&gt; will then construct the view from this class. Further, this class does not need to come from the model object &amp;mdash; other means of setting the row's class will exist that are unrelated to the model object involved.&lt;/p&gt;

&lt;h5&gt;Class structure to follow the data structure&lt;/h5&gt;

&lt;p&gt;To break the implementation down into manageable components, the design will use three classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ColumnView&lt;/code&gt; &amp;mdash; does all of the layout and manages the array of sections&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ColumnSection&lt;/code&gt; &amp;mdash; manages the array of rows in each section and stores header information&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RowView&lt;/code&gt; &amp;mdash; mostly a drawing class but does report the height for the row, given its data&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;ColumnView&lt;/h6&gt;

&lt;p&gt;The only binding for the &lt;code&gt;ColumnView&lt;/code&gt; is the &lt;code&gt;ColumnViewSectionArrayBinding&lt;/code&gt; which sets the &lt;code&gt;&lt;strong&gt;sectionsArray&lt;/strong&gt;&lt;/code&gt; property (&lt;code&gt;ColumnViewSectionArrayBinding&lt;/code&gt; is a globally defined string with the value &lt;code&gt;@"sectionsArray"&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Along with this binding, the &lt;code&gt;ColumnView&lt;/code&gt; has the following additional properties that can be set in the &lt;code&gt;ColumnViewSectionArrayBinding&lt;/code&gt; options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;strong&gt;sectionContentKey&lt;/strong&gt;&lt;/code&gt; &amp;mdash;A key path (relative to the section object) where the rows array can be found (if not present, it is assumed that the section &lt;em&gt;is&lt;/em&gt; the rows array).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;strong&gt;sectionClassKey&lt;/strong&gt;&lt;/code&gt; &amp;mdash; A key path (relative to the section object) where the default class to use for all rows in the section can be found (if not present the default &lt;code&gt;RowView&lt;/code&gt; class is used). This property is overridden by the &lt;code&gt;rowClassKey&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;strong&gt;rowClassKey&lt;/strong&gt;&lt;/code&gt; &amp;mdash; A key path (relative to the row object) where the class for the row can be found (if not present, it is assume the section &lt;em&gt;is&lt;/em&gt; the rows array).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;strong&gt;rowDisplayKey&lt;/strong&gt;&lt;/code&gt; &amp;mdash; A key path (relative to the row object) where a separate object used for display is found (if not present, the row object is used directly for display).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;strong&gt;headerDataKey&lt;/strong&gt;&lt;/code&gt; &amp;mdash; A key path (relative to the section object) where the object for the header is found (if not present, no header is shown for the section).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;strong&gt;headerClassKey&lt;/strong&gt;&lt;/code&gt; &amp;mdash; A key path (relative to the section object) where the class for the header row is found (if not present, the default &lt;code&gt;RowView&lt;/code&gt; class is used).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While you can set these properties directly on the &lt;code&gt;ColumnView&lt;/code&gt;, it is expected that they will be passed in the &lt;code&gt;options&lt;/code&gt; dictionary and picked up in the implementation of &lt;code&gt;bind:toObject:withKeyPath:options:&lt;/code&gt; on the &lt;code&gt;ColumnView&lt;/code&gt;.&lt;/p&gt;

&lt;h6&gt;ColumnSection&lt;/h6&gt;

&lt;p&gt;The &lt;code&gt;ColumnSection&lt;/code&gt; is a simple data class to manage data associated with a section. It looks like this:&lt;/p&gt;

&lt;pre&gt;@interface ColumnSection : NSObject
{
    NSArrayController *rowDataArrayController;
    NSString *rowClassKey;
    NSString *rowDisplayKey;
    
    Class defaultClass;
    
    id headerData;
    Class headerClass;
}&lt;/pre&gt;

&lt;p&gt;All of these properties are set by the &lt;code&gt;ColumnView&lt;/code&gt; using the properties it extracts from the &lt;code&gt;sectionsArray&lt;/code&gt; by following the key paths options from the binding.&lt;/p&gt;

&lt;p&gt;The array of row data is set by binding the &lt;code&gt;NSContentArrayBinding&lt;/code&gt; of the &lt;code&gt;rowDataArrayController&lt;/code&gt; instead of setting it directly as an &lt;code&gt;NSArray&lt;/code&gt; property. This is done so that the &lt;code&gt;ColumnSection&lt;/code&gt; can sort the array independent of the original data and so that the selection and other controller features of the &lt;code&gt;NSArrayController&lt;/code&gt; could be used if desired.&lt;/p&gt;

&lt;h6&gt;RowView&lt;/h6&gt;

&lt;p&gt;The &lt;code&gt;RowView&lt;/code&gt; has no bindings of its own &amp;mdash; it doesn't bindings since its data is passed to it by the &lt;code&gt;ColumnView&lt;/code&gt; which gets it from the &lt;code&gt;ColumnSection&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;Following the path of setting the data&lt;/h4&gt;

&lt;p&gt;To see how these bindings work to change the table, I'll explain what happens at each step.&lt;/p&gt;

&lt;h5&gt;1. The sectionsArray property is set by the binding&lt;/h5&gt;

&lt;p&gt;Immediately after you establish a binding, the bindings will set the value of the underlying property to be the same as the model object to which it is bound.&lt;/p&gt;

&lt;pre&gt;- (void)setSectionsArray:(NSArray *)newSectionsArray;&lt;/pre&gt;

&lt;p&gt;When the &lt;code&gt;sectionsArray&lt;/code&gt; is set by the &lt;code&gt;ColumnViewSectionArrayBinding&lt;/code&gt;, the &lt;code&gt;ColumnView&lt;/code&gt;'s &lt;code&gt;setSectionsArray:&lt;/code&gt; method is invoked where it constructs a &lt;code&gt;ColumnSection&lt;/code&gt; object for each section.&lt;/p&gt;

&lt;h5&gt;2. The constructed array of ColumnSections is set as the columnSections array&lt;/h5&gt;

&lt;pre&gt;- (void)setColumnSections:(NSArray *)newColumnSections;&lt;/pre&gt;

&lt;p&gt;The final step in the setter for &lt;code&gt;sectionsArray&lt;/code&gt; sets the &lt;code&gt;columnSections&lt;/code&gt; property of the &lt;code&gt;ColumnView&lt;/code&gt; using the constructed array of &lt;code&gt;ColumnSection&lt;/code&gt;s objects.&lt;/p&gt;

&lt;p&gt;This method observes the &lt;code&gt;rowDataArrayController&lt;/code&gt;'s &lt;code&gt;arrangedObjects&lt;/code&gt; (in case a row in the section changes) and triggers a reload of the view.&lt;/p&gt;

&lt;p&gt;If you wanted to bypass bindings for the sections (to use static, manually created sections), you could create and configure the &lt;code&gt;ColumnSection&lt;/code&gt; objects yourself and set them using this method.&lt;/p&gt;

&lt;h5&gt;3. Reload the view&lt;/h5&gt;

&lt;p&gt;The &lt;code&gt;ColumnView&lt;/code&gt; then accesses the properties on the &lt;code&gt;ColumnSection&lt;/code&gt; objects to populate the table. Only rows and headers that are visible are constructed, positioned and displayed.&lt;/p&gt;

&lt;p&gt;I show this code next time with the implementation of the &lt;code&gt;ColumnView&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;End result&lt;/h4&gt;

&lt;p&gt;The end result of a class designed this way is that configuring the &lt;code&gt;ColumnView&lt;/code&gt; is done with a single statement. For the screenshot I showed at the top, the &lt;code&gt;ColumnView&lt;/code&gt; is configured with data from the &lt;code&gt;ABAddressBook&lt;/code&gt; with a single statement:&lt;/p&gt;

&lt;pre&gt;[columnView
    bind:ColumnViewSectionArrayBinding
    toObject:[[AddressBookDataController sharedController] groupsController]
    withKeyPath:@"arrangedObjects"
    options:
        [NSDictionary dictionaryWithObjectsAndKeys:
            @"members", ColumnViewSectionContentKeyOption,
            kABGroupNameProperty, ColumnViewSectionHeaderDataKeyOption,
            @"Last", ColumnSectionRowDisplayKeyOption,
        nil]];&lt;/pre&gt;

&lt;p&gt;This selects the arranged groups from the &lt;code&gt;AddressBookDataController&lt;/code&gt; and uses them as sections. The title of each section is the group name, the content is the group's members and the object used for display is the lastname of the group member.&lt;/p&gt;

&lt;p&gt;This one statement replaces the 6 &lt;code&gt;dataSource&lt;/code&gt; and &lt;code&gt;delegate&lt;/code&gt; method implementations that &lt;code&gt;UITableView&lt;/code&gt; requires for the same functionality. If you create an IBPlugin for the view, you can configure all of this in Interface Builder and reduce the lines of code to zero.&lt;/p&gt;

&lt;p&gt;Obviously, I'm going through a small controller here: the &lt;code&gt;AddressBookDataController&lt;/code&gt;. This is because the &lt;code&gt;ABAddressBook&lt;/code&gt; does not send KVO notifications when &lt;code&gt;groups&lt;/code&gt; or their contents change and further, &lt;code&gt;ABGroup&lt;/code&gt;s are not &lt;code&gt;KVC&lt;/code&gt; compliant for their &lt;code&gt;members&lt;/code&gt; method. This controller is to address these problems, sort the groups by name and handle a situation where no groups exist. This work is not really bindings related and would be required in some form if the &lt;code&gt;ColumnView&lt;/code&gt; were configured another way.&lt;/p&gt;

&lt;h4&gt;To be continued...&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Matt, I can't help but notice you haven't shared the complete implementation of the &lt;code&gt;ColumnView&lt;/code&gt; class.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Well spotted, voice in my head. I wanted to focus on bindings and how to redesign an interface to work with them. I've already run way past the time I was going to spend on this. In my next post, I'll share more about the implementation and let you see all the code.&lt;/p&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-1765857822214061232?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/ZGoiesoEiB0" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1765857822214061232?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1765857822214061232?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/ZGoiesoEiB0/designing-view-with-bindings.html" title="Designing a view with Bindings (UITableView on the Mac)" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2010/03/designing-view-with-bindings.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQGQXo9fCp7ImA9WxBUFkw.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-7488742081135175174</id><published>2010-03-01T21:54:00.001-08:00</published><updated>2010-03-03T02:48:40.464-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-03T02:48:40.464-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="UIKit" /><category scheme="http://www.blogger.com/atom/ns#" term="performance tests" /><title>Load from NIB or construct views in code: which is faster?</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;You don't have to look far to find people suggesting that constructing views in code will increase the speed of your program. Since interface performance is a serious concern in iPhone development, I thought I'd look at the performance speed in creating complex iPhone UITableViewCells in code versus loading them from a NIB file.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;The sample program this time is pretty simple: an iPhone application that can load a table containing 20 rows (sized so that they will all fit onscreen), each row containing 20 fully-configured &lt;code&gt;UILabels&lt;/code&gt;, a &lt;code&gt;backgroundView&lt;/code&gt; and a &lt;code&gt;selectedBackgroundView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;All timing is done on the construct/load only. Adding cells to the table, configuring the cell for its row and drawing to the screen (all of which is identical in either load from NIB or construct in code cases) is not included as part of the timing results.&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/S4yPGfy6RTI/AAAAAAAAAl8/_OXzRuvd1yY/nibornot.png?imgmax=800" alt="nibornot.png" border="0" width="200" height="384" /&gt;

&lt;p&gt;The dark line across the right-hand side of each cell is just the word "placeholder" written 19 times on top of itself by the labels added to the cell.&lt;/p&gt;

&lt;blockquote&gt;You can download the sample project: &lt;a href="http://projectswithlove.com/projects/NibOrNot.zip"&gt;NibOrNot.zip&lt;/a&gt;&lt;/blockquote&gt;

&lt;h4&gt;Creating the cell in code&lt;/h4&gt;

&lt;p&gt;The construction of the cell in code looks like this:&lt;/p&gt;

&lt;pre&gt;cell = [[[UITableViewCell alloc]
	initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
cell.backgroundView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
cell.backgroundView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];

cell.selectedBackgroundView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
cell.selectedBackgroundView.backgroundColor = [UIColor colorWithWhite:0.85 alpha:1.0];

UILabel *firstLabel =
	[[[UILabel alloc] initWithFrame:CGRectMake(5, 0, 60, 20)] autorelease];
firstLabel.tag = 1;
firstLabel.font = [UIFont boldSystemFontOfSize:14];
firstLabel.shadowOffset = CGSizeMake(1,1);
firstLabel.textColor = [UIColor colorWithRed:0.0 green:0.2 blue:0.5 alpha:1.0];
firstLabel.backgroundColor = [UIColor clearColor];
firstLabel.text = @"placeholder";
firstLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
firstLabel.adjustsFontSizeToFitWidth = YES;
firstLabel.minimumFontSize = 10;
firstLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
firstLabel.lineBreakMode = UILineBreakModeTailTruncation;
firstLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
firstLabel.highlightedTextColor = [UIColor clearColor];

[cell addSubview:firstLabel];

//
// Plus the construction of a further 19 labels...
//&lt;/pre&gt;

&lt;p&gt;In this case, the next 19 labels could all be created in a loop (since they're all identical) but I wanted to code to reflect a proper view where each subview is distinct and has many properties uniquely applied &amp;mdash; so a basic loop is not necessarily appropriate.&lt;/p&gt;

&lt;h4&gt;Loading the NIB&lt;/h4&gt;

&lt;p&gt;There are many different ways to load a &lt;code&gt;UITableViewCell&lt;/code&gt; (loading just the &lt;code&gt;contentView&lt;/code&gt;, constructing a &lt;code&gt;UITableViewCell&lt;/code&gt; subclass and having it load the NIB, etc). I've gone for the quick and easy approach: loading the &lt;code&gt;UITableViewCell&lt;/code&gt; from the NIB in its entirety, passing my &lt;code&gt;UITableViewController&lt;/code&gt; as the owner.&lt;/p&gt;

&lt;pre&gt;[[NSBundle mainBundle] loadNibNamed:@"Cell" owner:self options:nil];
cell = loadedCell;
loadedCell = nil;&lt;/pre&gt;

&lt;p&gt;It may be hard to see how the &lt;code&gt;loadNibNamed:owner:options:&lt;/code&gt; method is connected to the other two lines. In this code, &lt;code&gt;loadedCell&lt;/code&gt; is an &lt;code&gt;IBOutlet&lt;/code&gt; on &lt;code&gt;self&lt;/code&gt;. When the NIB is loaded, it sets the &lt;code&gt;loadedCell&lt;/code&gt; value to be equal to the loaded cell (this is configured in the NIB file). After loading, I copy the &lt;code&gt;loadedCell&lt;/code&gt; into a local variable named &lt;code&gt;cell&lt;/code&gt; (which is later configured and returned) and set the instance variable on the class back to &lt;code&gt;nil&lt;/code&gt; (because we no longer need this pointer after returning it).&lt;/p&gt;

&lt;h4&gt;Simulator results&lt;/h4&gt;

&lt;p&gt;The first 10 results from the simulator look like this:&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;td&gt;Generated in code&lt;/td&gt;&lt;td&gt;Loaded from NIB&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.00153798 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.00184 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.00138998 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.00168097 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.00138199 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.00168198 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.00139898 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.001706 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.00167602 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.001697 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.00235301 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.00171804 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.00137097 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.002105 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.00138301 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.00173801 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.00140399 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.00171405 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.00137198 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.001692 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Constructing in code is generally about 20% faster &amp;mdash; although at 1 millisecond per construction in the simulator, it doesn't really matter.&lt;/p&gt;

&lt;h4&gt;Device results&lt;/h4&gt;

&lt;p&gt;The first 10 results running on my iPhone 3G look like this:&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;td&gt;Generated in code&lt;/td&gt;&lt;td&gt;Loaded from NIB&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.113011 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.131085 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.114312 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.097244 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.101614 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.08413 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.105022 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.081331 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.10087 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.093407 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.105968 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.083472 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.100045 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.091788 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.105458 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.083763 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.098836 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.08714 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.102028 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.109811 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;The construction in code is about 15% faster on the first construction but by the third cell, &lt;em&gt;loading from the NIB file is 17% faster&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Running some CPU sampling in Instruments, I was able to work out that &lt;code&gt;adjustsFontSizeToFitWidth&lt;/code&gt; was the critical factor here: it appears that Interface Builder precalculates the correct size based on the placeholder string, whereas the constructed code is forced to do this at runtime, causing its performance to suffer.&lt;/p&gt;

&lt;p&gt;Turning off &lt;code&gt;adjustsFontSizeToFitWidth&lt;/code&gt; in both the generated code and the loaded code (replaced the &lt;code&gt;label.adjustsFontSizeToFitWidth = YES&lt;/code&gt; with &lt;code&gt;label.adjustsFontSizeToFitWidth = NO&lt;/code&gt; and switched &lt;em&gt;Cell.xib&lt;/em&gt; to &lt;em&gt;Cell2.xib&lt;/em&gt;), gave the following results:&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;td&gt;Generated in code&lt;/td&gt;&lt;td&gt;Loaded from NIB&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.085553 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.095012 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.077257 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.087141 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.084639 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.082693 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.079142 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.098218 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.078286 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.082136 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.087895 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.087088 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.0792 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.082335 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.084037 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.082358 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.076416 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.08714 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generated cell in 0.078426 seconds&lt;/td&gt;&lt;td&gt;Loaded cell in 0.084312 seconds&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;This now swings the performance advantage back to handwritten code by 7%.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can download the sample project: &lt;a href="http://projectswithlove.com/projects/NibOrNot.zip"&gt;NibOrNot.zip&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;Don't assume that NIB files are always slower than generating views in code &amp;mdash; it is not always true. While in general, generating user interface views in code appears to be 5-10% faster than loading from a NIB, the reality is that this difference is small enough that it doesn't matter and there are certainly some views that load faster from a NIB than from code.&lt;/p&gt;

&lt;p&gt;This doesn't mean that construction speed is unimportant on the iPhone; it clearly is. I was able to create a (slightly contrived) view that took nearly two seconds to load (unacceptably slow). However, saving 10% by moving from NIBs to creating views in code will never fix the problem (1.8 seconds is still too slow). In this case, flattening the view hierarchy (using a single custom view to draw what multiple subviews used to draw), or removing text fields entirely, is the best way to improve performance. This type of redesign can improve performance by a factor of 10 or more.&lt;/p&gt;

&lt;p&gt;The conclusion to be drawn is that when choosing to use a NIB file or not, you should use whatever you're most comfortable with and whatever will keep your code maintenance costs low. Don't be concerned that one approach or the other will cause your UI performance to suffer.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-7488742081135175174?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/xN8VomQNJns" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7488742081135175174?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7488742081135175174?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/xN8VomQNJns/load-from-nib-or-construct-views-in.html" title="Load from NIB or construct views in code: which is faster?" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2010/03/load-from-nib-or-construct-views-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcMRX87cSp7ImA9WxBUEUo.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-4234539046597446994</id><published>2010-02-26T00:35:00.001-08:00</published><updated>2010-02-26T01:21:24.109-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-26T01:21:24.109-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="self promotion" /><title>StreamToMe 2.0 is out (and Cocoa With Love is 2 years old).</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Two different things turning two different kinds of "2". Snap.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Cocoa With Love is two years old today&lt;/h4&gt;

&lt;p&gt;I've been writing a feature article every week for two years now &amp;mdash; haven't missed a single week yet (hope that doesn't jinx me).&lt;/p&gt;

&lt;p&gt;To commemorate, I've put the complete list of downloadable code samples from my blog on the &lt;a href="http://projectswithlove.com/projects/"&gt;Projects With Love: Open Source Projects&lt;/a&gt; page.&lt;/p&gt;

&lt;h4&gt;StreamToMe 2.0 is out!&lt;/h4&gt;

&lt;p&gt;For those who don't know, &lt;a href="http://projectswithlove.com/streamtome/index.html"&gt;StreamToMe&lt;/a&gt; is an iPhone application for streaming video and music from your Mac to your iPhone/iPod Touch. Plug your phone into your TV and you can use it to stream your Mac's music and video files to your TV. No prior conversion necessary &amp;mdash; a huge range of codecs and formats (including AVI, WMV, MOV, MP4, FLV and more) will just play.&lt;/p&gt;

&lt;p&gt;StreamToMe 2.0 adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Thumbnail previews for video files&lt;/li&gt;
&lt;li&gt;Album artwork for music files (including while playing)&lt;/li&gt;
&lt;li&gt;Artist and title metadata display&lt;/li&gt;
&lt;li&gt;Subtitle rendering (including SRT and SSA files, MKV embedded SSA tracks and MOV text tracks)&lt;/li&gt;
&lt;li&gt;Multiple audio tracks&lt;/li&gt;
&lt;li&gt;Continuous and random play modes&lt;/li&gt;
&lt;li&gt;Sort options including folder flattening (so you can view the full hierarchy of your iTunes collection as a single flat collection)&lt;/li&gt;
&lt;li&gt;Preliminary support for EyeTV streams&lt;/li&gt;
&lt;li&gt;Persistent playback &amp;mdash; if you quit or are interrupted by a phone call during playback, you can continue from where you were.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And more!&lt;/p&gt;

&lt;blockquote&gt;&lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=325327899&amp;mt=8"&gt;&lt;img src="http://projectswithlove.com/streamtome/streamtome-icon.png" style="float:left;margin:0px;margin-right:16px;padding:0px;" width="64px" height="64px"&gt;&lt;/a&gt;
	&lt;p&gt;StreamToMe is available to purchase from the iTunes App Store:&lt;/p&gt;
	&lt;p&gt;&lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=325327899&amp;mt=8"&gt;&lt;strong&gt;Download StreamToMe 2.0 from the AppStore now&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
	&lt;div style="clear:both"&gt;&lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;Free upgrade for existing customers. Lucky them! Don't forget to update &lt;a href="http://projectswithlove.com/streamtome/servetome.html"&gt;ServeToMe&lt;/a&gt; to enable some of the newer features.&lt;/p&gt;

&lt;p&gt;Windows XP support for ServeToMe is coming soon (I'm hoping by the end of March).&lt;/p&gt;

&lt;p&gt;Here's a few screenshots of the new version of StreamToMe in action:&lt;/p&gt;

&lt;p style="text-align:center;"&gt;
	&lt;img width="180px" height="270px" src="http://projectswithlove.com/streamtome/screenshot2_folders.png" style="display:inline;"&gt;
	&lt;img width="180px" height="270px" src="http://projectswithlove.com/streamtome/screenshot3_loading.png" style="display:inline;"&gt;
	&lt;img width="180px" height="270px" src="http://projectswithlove.com/streamtome/screenshot5_music.png" style="display:inline;"&gt;&lt;br/&gt;
	&lt;img width="270px" height="180px" src="http://projectswithlove.com/streamtome/screenshot4_movieplaying.png" style="display:inline;"&gt;
	&lt;img width="180px" height="270px" src="http://projectswithlove.com/streamtome/screenshot6_musicplaying.png" style="display:inline;"&gt;&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-4234539046597446994?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/KMnvFk4g44M" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/4234539046597446994?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/4234539046597446994?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/KMnvFk4g44M/streamtome-20-is-out-and-cocoa-with.html" title="StreamToMe 2.0 is out (and Cocoa With Love is 2 years old)." /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2010/02/streamtome-20-is-out-and-cocoa-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QGRXgzfip7ImA9WxBVGU0.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-172879585462204482</id><published>2010-02-21T20:27:00.001-08:00</published><updated>2010-02-22T22:08:44.686-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-22T22:08:44.686-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><category scheme="http://www.blogger.com/atom/ns#" term="Standard C" /><title>Resolving a path containing a mixture of aliases and symlinks</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Resolving symlinks in a path is very easy in Cocoa (it can be done in a single statement) but aliases require more work. Additionally the commands for resolving symlinks and aliases are incompatible with each other &amp;mdash; meaning that you can resolve a path containing symlinks or aliases but not a mixture of the two. In this post, I present a category on &lt;code&gt;NSString&lt;/code&gt; that will allow you to resolve a path containing any combination of symlinks or aliases as simply as resolving symlinks alone.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;When Apple introduced &lt;a href="http://en.wikipedia.org/wiki/Alias_(Mac_OS)"&gt;alias files&lt;/a&gt; in &lt;a href="http://en.wikipedia.org/wiki/System_7_(Macintosh)"&gt;System 7&lt;/a&gt;, they were the only way of referencing another file in the filesystem. Sure, other operating systems already had &lt;a href="http://en.wikipedia.org/wiki/Symbolic_link"&gt;symlinks&lt;/a&gt; but there was little likelihood of the two needing to interact since System 7 had almost no interoperability with Unix filesystems (despite the existence of &lt;a href="http://en.wikipedia.org/wiki/A/UX"&gt;A/UX&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Alias files are a great way of referencing other files because they can continue to track their target if it moves. Aliases store both the path of their target and the &lt;a href="http://en.wikipedia.org/wiki/Inode"&gt;inode&lt;/a&gt; plus volume identifier of their target. This means that they won't break if the file at their target path moves, unlike a symlink which will break if the target moves (since a symlink is just a path). In fact, symlinks will often break if the symlink file itself moves since symlinks are normally relative paths.&lt;/p&gt;

&lt;p&gt;Aliases do have some annoying traits. In their current incarnation, they insist on storing the thumbnail and metadata of data of their target, resulting in a file which may be hundreds of kilobytes (or more) of entirely redundant data &amp;mdash; especially annoying if you have thousands of aliases. Despite this, they are normally a good, general-purpose way of linking files in the filesystem.&lt;/p&gt;

&lt;p&gt;As a "user-exposed" feature (unlike symlinks which are largely hidden from novice users) they are also common. It's unfortunate then that they're so annoying to deal with in Cocoa.&lt;/p&gt;

&lt;h4&gt;Resolving aliases&lt;/h4&gt;

&lt;p&gt;Resolving a symlink is easy:&lt;/p&gt;

&lt;pre&gt;NSString *resolvedPath = [path stringByResolvingSymlinksInPath];&lt;/pre&gt;

&lt;p&gt;Theoretically, you only need one command to resolve an alias:&lt;/p&gt;

&lt;pre&gt;OSErr err = FSResolveAliasFile(
    &amp;fsRef, resolveAliasChains, &amp;targetIsFolder, &amp;wasAliased);&lt;/pre&gt;

&lt;p&gt;Unfortunately, the &lt;code&gt;FSRef&lt;/code&gt; here is a campy 1990's throwback (the 90's are now two decades ago) and in Cocoa programming, you rarely have or want an &lt;code&gt;FSRef&lt;/code&gt; for a file. This means that you need to convert your &lt;code&gt;NSString&lt;/code&gt; to an &lt;code&gt;FSRef&lt;/code&gt; and then convert the result back to an &lt;code&gt;NSString&lt;/code&gt; when you're done.&lt;/p&gt;

&lt;p&gt;Apple's Low Level File Management Topics include &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/LowLevelFileMgmt/Articles/ResolvingAliases.html"&gt;an approach for resolving an alias from an &lt;code&gt;NSString&lt;/code&gt; path&lt;/a&gt; which demonstrates this procedure. While I use an implementation derived from this in my solution, Apple's original implementation suffers from the following problems:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;The &lt;code&gt;CFURLGetFSRef&lt;/code&gt; function used to convert a &lt;code&gt;CFURL&lt;/code&gt; into an &lt;code&gt;FSRef&lt;/code&gt; will fail if the path contains an alias at anywhere other than the last path component.&lt;/li&gt;
&lt;li&gt;While &lt;code&gt;CFURLGetFSRef&lt;/code&gt; will follow symlinks in the URL to create the &lt;code&gt;FSRef&lt;/code&gt;, no part of this code will actually return a resolved symlink, so that part will require a separate step.&lt;/li&gt;
&lt;li&gt;The function &lt;code&gt;FSResolveAliasFile&lt;/code&gt; will present a user dialog if the alias points to a volume which is not mounted. While potentially desirable in a user application, this is undesirable in all other cases.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;This final point is not too difficult &amp;mdash; we'll replace &lt;code&gt;FSResolveAliasFile&lt;/code&gt; with &lt;code&gt;FSResolveAliasFileWithMountFlags&lt;/code&gt; which allows us to disable the user dialog using the flags. But the remaining two points will require a little more work to address.&lt;/p&gt;

&lt;p&gt;As a further comment about usage of &lt;code&gt;FSResolveAliasFileWithMountFlags&lt;/code&gt;: aliases that point to other aliases are exceedingly rare (if you try to create an alias to an alias in the Finder, the Finder will make the second alias point directly to the target) so I pass &lt;code&gt;false&lt;/code&gt; for &lt;code&gt;resolveAliasChains&lt;/code&gt; to optimize for the unchained case and handle the unusual case of chained aliases at a different level in the code.&lt;/p&gt;

&lt;h4&gt;Breaking it down into solvable components&lt;/h4&gt;

&lt;p&gt;We can resolve paths that contain any number of symlinks and we can resolve a path that contains an alias but we can't do both at once.&lt;/p&gt;

&lt;p&gt;The solution is therefore straightforward:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;break the path down into components&lt;/li&gt;
&lt;li&gt;build the components together, iteratively resolving aliases or symlinks at each level&lt;/li&gt;
&lt;li&gt;implement code for resolving the symlink or alias as efficiently as possible for the bottom level of this scenario&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Each of these points will then be a different tier in a three level solution.&lt;/p&gt;

&lt;p&gt;My solution will contain two requirements:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;The initial path must be resolvable to an absolute path using &lt;code&gt;-[NSString stringByStandardizingPath]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The path contained within a symlink file will not include any aliases or symlinks except as the final string component (no recursive parsing)&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;This second point is mostly a theoretical limitation since it is nearly impossible to generate a symlink with an alias or other symlink as a non-final path component (you'd have to create the symlink file manually).&lt;/p&gt;

&lt;h4&gt;Top level&lt;/h4&gt;

&lt;p&gt;The top level of the solution is simply an iteration over path components which then invokes the iterative link resolution.&lt;/p&gt;

&lt;pre&gt;&lt;strong&gt;// Break into components.&lt;/strong&gt;
NSArray *pathComponents = [path pathComponents];

&lt;strong&gt;// First component ("/") needs no resolution; we only need to handle subsequent
// components.&lt;/strong&gt;
NSString *resolvedPath = [pathComponents objectAtIndex:0];
pathComponents =
    [pathComponents subarrayWithRange:NSMakeRange(1, [pathComponents count] - 1)];

&lt;strong&gt;// Process all remaining components.
&lt;/strong&gt;for (NSString *component in pathComponents)
{
    resolvedPath = [resolvedPath stringByAppendingPathComponent:component];
    resolvedPath = [resolvedPath stringByIterativelyResolvingSymlinkOrAlias];
    if (!resolvedPath)
    {
        return nil;
    }
}&lt;/pre&gt;

&lt;p&gt;I haven't shown the code which resolves the path to an absolute path or fails but the assumption that it begins with a "/" is valid.&lt;/p&gt;

&lt;h4&gt;Middle level&lt;/h4&gt;

&lt;p&gt;The middle level of the solution iterates over a path where only the final component could be a symlink or alias and resolves it until the result is neither an alias nor symlink.&lt;/p&gt;

&lt;p&gt;For efficiency, this does two things in an unusual way:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;I use &lt;code&gt;lstat&lt;/code&gt; instead of &lt;code&gt;-[NSFileManager attributesOfItemAtPath:error]&lt;/code&gt; since I only need the &lt;code&gt;st_mode&lt;/code&gt; field, and &lt;code&gt;NSFileManager&lt;/code&gt; invokes &lt;code&gt;lstat&lt;/code&gt; internally anyway.&lt;/li&gt;
&lt;li&gt;I use my own &lt;code&gt;-[NSString stringByConditionallyResolvingSymlink]&lt;/code&gt; method instead of &lt;code&gt;- [NSString stringByResolvingSymlinksInPath]&lt;/code&gt; since I know that only the final component requires resolution (I've already done the work for earlier components).&lt;/li&gt;&lt;/ul&gt;

&lt;pre&gt;- (NSString *)stringByIterativelyResolvingSymlinkOrAlias
{
    NSString *path = self;
    NSString *aliasTarget = nil;
    struct stat fileInfo;
    
    &lt;strong&gt;// Use lstat to determine if the file is a directory or symlink&lt;/strong&gt;
    if (lstat([[NSFileManager defaultManager]
        fileSystemRepresentationWithPath:path], &amp;fileInfo) &lt; 0)
    {
        return nil;
    }
    
    &lt;strong&gt;// While the file is a symlink or resolves as an alias, keep iterating.&lt;/strong&gt;
    while (S_ISLNK(fileInfo.st_mode) ||
        (!S_ISDIR(fileInfo.st_mode) &amp;&amp;
            (aliasTarget = [path stringByConditionallyResolvingAlias]) != nil))
    {
        if (S_ISLNK(fileInfo.st_mode))
        {
            &lt;strong&gt;// Resolve the symlink component in the path&lt;/strong&gt;
            NSString *symlinkPath = [path stringByConditionallyResolvingSymlink];
            if (!symlinkPath)
            {
                return nil;
            }
            path = symlinkPath;
        }
        else
        {
            &lt;strong&gt;// Or use the resolved alias result&lt;/strong&gt;
            path = aliasTarget;
        }

        &lt;strong&gt;// Use lstat again to prepare for the next iteration&lt;/strong&gt;
        if (lstat([[NSFileManager defaultManager]
            fileSystemRepresentationWithPath:path], &amp;fileInfo) &lt; 0)
        {
            path = nil;
            continue;
        }
    }
    
    return path;
}&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;stringByConditionallyResolvingAlias&lt;/code&gt; method returns &lt;code&gt;nil&lt;/code&gt; if the path exists but isn't an alias, allowing this function to double as both a test for whether the path is an alias as well as the resolution of that alias. I could use a similar approach to test and resolve symlinks (since I have also implemented a &lt;code&gt;stringByConditionallyResolvingSymlink&lt;/code&gt; method) but I don't do this for aforementioned efficiency reasons: it would cause an extra fetch of the filesystem metadata which is the main bottleneck of the whole procedure.&lt;/p&gt;

&lt;h4&gt;Bottom level&lt;/h4&gt;

&lt;p&gt;The bottom level is then just the implementation of the &lt;code&gt;stringByConditionallyResolvingAlias&lt;/code&gt; and &lt;code&gt;stringByCondictionallyResolvingSymlink&lt;/code&gt;. The first is just a modification of Apple's code to address the issues I've already discussed &amp;mdash; you can see the final product by downloading the code. The second method looks like this:&lt;/p&gt;

&lt;pre&gt;- (NSString *)stringByConditionallyResolvingSymlink
{
    &lt;strong&gt;// Get the path that the symlink points to&lt;/strong&gt;
    NSString *symlinkPath =
        [[NSFileManager defaultManager]
            destinationOfSymbolicLinkAtPath:self
            error:NULL];
    if (!symlinkPath)
    {
        return nil;
    }
    if (![symlinkPath hasPrefix:@"/"])
    {
        &lt;strong&gt;// For relative path symlinks (common case), resolve the relative&lt;/strong&gt;
        &lt;strong&gt;// components&lt;/strong&gt;
        symlinkPath =
            [[self stringByDeletingLastPathComponent]
                stringByAppendingPathComponent:symlinkPath];
        symlinkPath = [symlinkPath stringByStandardizingPath];
    }
    return symlinkPath;
}&lt;/pre&gt;

&lt;p&gt;Hooray, I finally used &lt;code&gt;NSFileManager&lt;/code&gt; in a post about files! Yes, once again it's probably just a wrapper around the C function &lt;code&gt;readlink&lt;/code&gt; that I could invoke for myself but the fact that the &lt;code&gt;NSFileManager&lt;/code&gt; method handles the nasty business of buffer allocation, sizing and string conversion is more than enough reason to forego the lower level function.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can download &lt;a href="http://projectswithlove.com/projects/NSString+SymlinksAndAliases.zip"&gt;NSString+SymLinksAndAliases.zip&lt;/a&gt; (3kb) which contains all the code discussed in this post (plus a few other related methods) as a category on &lt;code&gt;NSString&lt;/code&gt;.&lt;/blockquote&gt;

&lt;p&gt;Usage of the category is as simple as importing the header and writing:&lt;/p&gt;

&lt;pre&gt;NSString *fullyResolvedPath = [somePath stringByResolvingSymlinksAndAliases];&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;fullyResolvedPath&lt;/code&gt; will either contain the destination (as an absolute and fully resolved path) or it will be &lt;code&gt;nil&lt;/code&gt; (if the path can't be fully resolved because it doesn't exist or can't be read for some reason).&lt;/p&gt;

&lt;p&gt;I've tried to keep this code efficient by keeping the number of filesystem calls low. The code will certainly handle at least a few thousand alias resolutions per second on my computer but I haven't pushed it much harder than that.&lt;/p&gt;

&lt;p&gt;Of course, if you're an iPhone programmer, all of this is a waste of time since the iPhone doesn't publicly expose &lt;code&gt;FSRef&lt;/code&gt; (although &lt;code&gt;CFURLGetFSRef&lt;/code&gt; exists to generate a pointer which is totally unusable). In fact, I'm not sure aliases are possible on the iPhone anyway.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-172879585462204482?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/mWj-Arl90jM" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/172879585462204482?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/172879585462204482?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/mWj-Arl90jM/resolving-path-containing-mixture-of.html" title="Resolving a path containing a mixture of aliases and symlinks" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2010/02/resolving-path-containing-mixture-of.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUDQXo-fip7ImA9WxBVFEo.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-6838077478115905557</id><published>2010-02-16T00:32:00.001-08:00</published><updated>2010-02-17T21:51:10.456-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-17T21:51:10.456-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Core Data" /><title>The differences between Core Data and a Database</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;The &lt;a href="http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/CoreData/index.html"&gt;Core Data Programming Guide&lt;/a&gt; clearly states that Core Data is not a database but since both Core Data and a database are ways of providing searchable, persistent storage, exactly how and why they are different may not be clear. In this post, I'll look at the way Core Data works and the reasons why its features and capabilities are different to those of common SQL databases &amp;mdash; even though an SQL database may be used as the backing store.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Introduction&lt;/h4&gt;

&lt;p&gt;Both Core Data and an SQL database provide a means of persistently storing structured data in a searchable store.&lt;/p&gt;

&lt;p&gt;Since programmers are generally familiar with databases and since Core Data is actually backed by an SQLite database, it is understandable that Core Data is often treated and used as though it were a wrapper around SQLite.&lt;/p&gt;

&lt;p&gt;It is important to realize that although you can use Core Data in this way (in fact, it works very well like this), that Core Data actually operates over a different domain to SQLite &amp;mdash; meaning that it provides lots of services that SQLite doesn't but also that Core Data can't provide some of the services that SQLite can. Even for services that both technologies provide, there are different performance considerations.&lt;/p&gt;

&lt;h4&gt;Primary function of a database&lt;/h4&gt;

&lt;p&gt;The somewhat narrow description of database that I will use is: persistent and searchable storage for data in table, row, column format where the primary goal is to keep the data up-to-date on disk at all times, with a secondary goal of powerful, focussed, narrow fetching and updating capabilities.&lt;/p&gt;

&lt;p&gt;There are lots of database implementations and many provide features far beyond this description but I'm really looking at the key components of a straightforward SQLite-style database implementation with which many programmers are familiar.&lt;/p&gt;

&lt;p&gt;Despite many databases being called "relational" (which implies that they have a degree of support for object connectivity), SQLite and many other relational databases don't handle the mechanics of connecting objects; maintaining state (like a an object relation) between columns, rows or tables is left to the user of the database. In this sense, a database is "dumb" storage &amp;mdash; rows have few behaviors beyond "read" and "write" and extending or customizing their behavior would involve extending the database system itself. Even when triggers are available, their programmatic capabilities are limited.&lt;/p&gt;

&lt;h4&gt;Primary function of Core Data&lt;/h4&gt;

&lt;p&gt;At its heart, Core Data is an object graph manager with lifecycle, searching and persistence features. In the case of Core Data, object graph management includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can connect object A to object B and the connection at both the A and B ends is kept perpetually in sync.&lt;/li&gt;
&lt;li&gt;If you change the connection at the A end, the B end will be updated and all changes trigger notifications (to which you can attach arbitrary code)&lt;/li&gt;
&lt;li&gt;Deletion of objects at one end of a connection can trigger cascading deletion or nullify responses.&lt;/li&gt;
&lt;li&gt;The other end of a connection can exist out of memory (faulted) unless the connection is actually followed at which time the connected object is loaded.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike a typical database, Core Data can be used totally in-memory. While Core Data is often called a "object persistence" framework (since it is expected that you will use its persistence features), it is actually possible to use Core Data entirely in-memory without any form of persistence. Of course, once you have data, it is reasonable to want to keep that data, so persistence is treated as a major feature of the framework but it is important to know that persistence is not mandatory.&lt;/p&gt;

&lt;p&gt;Also unlike a database, it is possible to use Core Data without any form of searching. If you allocate and connect all your objects, all you need to do is hold onto one of them and you can walk through everything without needing a fetch request. This search-less behavior is not because Core Data transparently performs a search: once data is loaded in memory, following a connection does not involve a search.&lt;/p&gt;

&lt;p&gt;All Core Data objects are fully instantiated Objective-C objects that manage most of their own attributes, relationships and lifecycle. This also means that their properties and behaviors are implemented by methods, making them both observable and overrideable.&lt;/p&gt;

&lt;h4&gt;Databases and object graph management are not inherently exclusive&lt;/h4&gt;

&lt;p&gt;While not available by default in SQLite, the "foreign key" of MySQL, and other SQL:2003 compliant databases, can handle keeping identifiers in different tables in sync and even cascade deletion when requested. The programmatic customization abilities of overrideable objects is not available but the basics of graph management are there.&lt;/p&gt;

&lt;p&gt;There are other object relational frameworks that work closer to Core Data's model but which try to behave as an atomic, transactional database. To update the object graph, these frameworks must:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;load appropriate rows from a database&lt;/li&gt;
&lt;li&gt;instantiate objects from these rows&lt;/li&gt;
&lt;li&gt;make changes to the graph objects that are now in memory&lt;/li&gt;
&lt;li&gt;commit the changes back to the database&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;To be properly atomic, these steps must all be performed as a single transaction (with no other reads or write to the affected rows during the transaction). While some systems might require this, it is far too slow for a general object graph system.&lt;/p&gt;

&lt;p&gt;Core Data does not follow this model as Core Data aims to be a more general object management system &amp;mdash; and that means that it needs far better performance and flexibility than this model would allow.&lt;/p&gt;

&lt;h4&gt;Operating in-memory versus an on-disk database&lt;/h4&gt;

&lt;p&gt;Without access to the source code, it's not entirely clear. We can only assume that the &lt;code&gt;NSManagedObjectContext&lt;/code&gt; tracks instantiated objects in a heap or structured container of some form so that it can find them again.&lt;/p&gt;

&lt;p&gt;This tracking structure may behave a bit like an in-memory database but it would only be for tracking the existence of instantiated objects &amp;mdash; it is important to note that it would not itself store any data. Also note that the centralized &lt;code&gt;NSManagedObjectContext&lt;/code&gt; and any structures it might maintain are not how you interact with instantiated &lt;code&gt;NSManagedObject&lt;/code&gt;s &amp;mdash; you interact with an &lt;code&gt;NSManagedObject&lt;/code&gt; by sending messages to &lt;code&gt;NSManagedObject&lt;/code&gt; pointers.&lt;/p&gt;

&lt;p&gt;The reason that Core Data focuses on an in-memory representation is speed. For object graph changes that affect multiple objects, it is much faster if they are all in memory already, rather than needing to search for them again in the database.&lt;/p&gt;

&lt;p&gt;For temporary objects (data that doesn't have to be saved to disk) Core Data can create, change and manipulate objects much faster than SQLite can since SQLite has to update indexes and update nodes in the B-tree, as well as simply allocating space and setting values. Core Data can allocate millions of objects in a few seconds, where SQLite might take a few minutes for the same number of allocations.&lt;/p&gt;

&lt;p&gt;The tradeoff with an in-memory approach is that SQLite is still used as the backing store. Reading from disk and saving to disk involves all of SQLite's overheads plus the overhead of the Core Data to SQLite conversion process &amp;mdash; so is invariably slower than SQLite alone.&lt;/p&gt;

&lt;h4&gt;Common database tasks that Core Data doesn't do&lt;/h4&gt;

&lt;p&gt;I've spoken about features that Core Data has that databases do not. It is important to consider some of the features that Core Data's approach lacks with respect to a database.&lt;/p&gt;

&lt;h5&gt;Core Data cannot operate on data without loading the data into memory&lt;/h5&gt;

&lt;p&gt;In SQL you can simply "&lt;code&gt;DROP tableName&lt;/code&gt;" to delete whole tables or update every column of a table with commands like "&lt;code&gt;UPDATE tableName SET key1 = value WHERE key2 = otherValue&lt;/code&gt;". These commands can efficiently update vast amounts of data because they only need to load small amounts of data into RAM at any given time.&lt;/p&gt;

&lt;p&gt;Core Data doesn't work in this perpetually on-disk manner &amp;mdash; it only works on objects in memory. Even if you only want to delete an object, it must be loaded and instantiated in RAM.&lt;/p&gt;

&lt;p&gt;Of course, this is necessary because the object, and its potentially overridden behaviors must be loaded and invoked. There are also connections to be kept up to date with other objects.&lt;/p&gt;

&lt;p&gt;However this constraint has implications: if you're trying to change huge numbers of objects (tens of thousands or more) you will need to consider keeping your memory footprint down. This can be done by periodically refaulting unchanged values (&lt;code&gt;refreshObject:mergeChanges:&lt;/code&gt;) or avoiding the fetch of an object's data (&lt;code&gt;setIncludesPropertyValues:NO&lt;/code&gt; on &lt;code&gt;NSFetchRequest&lt;/code&gt;) or even saving the whole context and releasing all the objects you're holding.&lt;/p&gt;

&lt;h5&gt;Core Data does not handle data logic&lt;/h5&gt;

&lt;p&gt;There are a few data-related features that SQL contains, a good example being "unique" keys, that Core Data does not include.&lt;/p&gt;

&lt;p&gt;There are a couple of technical reasons why this might be the case. Subclasses can override the getter and setter for an attribute to the point where it is unclear whether it is or is not unique. In fact, transient Core Data attributes need not even support &lt;code&gt;isEqual:&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, I suspect the distinction is actually that Core Data offers no real support for attribute behaviors at all. Core Data manages the "graph" (connections) but the data attributes are all the responsibility of the business logic in the rest of the program; convenient as it may be, it falls outside Core Data's conceptual domain.&lt;/p&gt;

&lt;h5&gt;Multi-threaded, multi-user scenarios&lt;/h5&gt;

&lt;p&gt;Core Data does not offer any amount of threading support. To be fair, &lt;code&gt;SQLite&lt;/code&gt; is single threaded too but many other databases are multi-threaded and multi-user.&lt;/p&gt;

&lt;p&gt;Core Data has been designed for single-user environments (running inside desktop and iPhone apps). Getting rid of threading and locking makes the framework much faster and simpler to work with in its standard usage scenarios.&lt;/p&gt;

&lt;p&gt;However, there are still situations where you will want multiple threads reading your data. &lt;code&gt;NSManagedObject&lt;/code&gt;s and their &lt;code&gt;NSManagedObjectContext&lt;/code&gt; should be accessed from a single thread only. If you need another thread working on the same data, you need to save the file and reopen using a different &lt;code&gt;NSManagedObjectContext&lt;/code&gt; in the other thread.&lt;/p&gt;

&lt;h4&gt;Summary&lt;/h4&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Core Data&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;Primary function is storing and fetching data&lt;/td&gt;&lt;td&gt;Primary function is graph management (although reading and writing to disk is an important supporting feature)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Operates on data stored on disk (or minimally and incrementally loaded)&lt;/td&gt;&lt;td&gt;Operates on objects stored in memory (although they can be lazily loaded from disk)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Stores "dumb" data&lt;/td&gt;&lt;td&gt;Works with fully-fledged objects that self-manage a lot of their behavior and can be subclassed and customized for further behaviors&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Can be transactional, thread-safe, multi-user&lt;/td&gt;&lt;td&gt;Non-transactional, single threaded, single user (unless you create an entire abstraction around Core Data which provides these things)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Can drop tables and edit data without loading into memory&lt;/td&gt;&lt;td&gt;Only operates in memory&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Perpetually saved to disk (and often crash resilient)&lt;/td&gt;&lt;td&gt;Requires a save process&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Can be slow to create millions of new rows&lt;/td&gt;&lt;td&gt;Can create millions of new objects in-memory very quickly (although saving these objects will be slow)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Offers data constraints like "unique" keys&lt;/td&gt;&lt;td&gt;Leaves data constraints to the business logic side of the program&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-6838077478115905557?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/Pi6AzPXpCRQ" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/6838077478115905557?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/6838077478115905557?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/Pi6AzPXpCRQ/differences-between-core-data-and.html" title="The differences between Core Data and a Database" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2010/02/differences-between-core-data-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYERX0_fCp7ImA9WxBVEUU.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-6108577800484223211</id><published>2010-02-08T02:26:00.001-08:00</published><updated>2010-02-14T14:38:24.344-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-14T14:38:24.344-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cocoa Touch" /><category scheme="http://www.blogger.com/atom/ns#" term="Xcode" /><category scheme="http://www.blogger.com/atom/ns#" term="performance tests" /><category scheme="http://www.blogger.com/atom/ns#" term="Standard C" /><title>Custom build rules, generated tables and faster floating point</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;As fast as computers are, heavy use of floating point functions can still slow them down. One way around this, is to use a lookup table instead of calculating floating point values at runtime. But keeping a generated table up-to-date is annoying work. In this post, I'll show you how to create a lookup table automatically using a custom build rule, making an OpenGL animation 5 times faster in the process.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In this post, I'm going to work with a modified version of Apple's default OpenGL ES 1.0 program. In this program, a colored square will spin in the center of the window:&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/S2_A9YV4WSI/AAAAAAAAAlc/p3cUfen0mn0/spinner.png?imgmax=800" alt="spinner.png" border="0" width="156" height="300" /&gt;

&lt;blockquote&gt;&lt;a href="http://projectswithlove.com/projects/Spinner.zip"&gt;Download the complete project for this post: Spinner.zip&lt;/a&gt; (25kb).&lt;/blockquote&gt;

&lt;p&gt;To artificially create a situation where this simple program is bound by CPU performance, I will calculate the location of the square thousands of times for every frame.&lt;/p&gt;

&lt;h4&gt;Initial code and performance&lt;/h4&gt;

&lt;p&gt;The initial code for updating the model matrix before drawing is:&lt;/p&gt;

&lt;pre&gt;static float transX = 3.14159265f * 0.5;
static float transY = 0.0f;
for (int i = 0; i &lt; 2e5; i++)
{
    translateX = sinf(transX)/2.0f;
    translateY = sinf(transY)/2.0f;
    doNothingff(&amp;translateX, &amp;transX);
    doNothingff(&amp;translateY, &amp;transY);
}
transX += 0.075f;
transY += 0.075f;

glTranslatef((GLfloat)(translateX), (GLfloat)(translateY), 0.0f);&lt;/pre&gt;

&lt;p&gt;This is a very simple calculation: it translates out to the edge of the unit circle and progresses around the circle by 0.075 radians per frame.&lt;/p&gt;

&lt;p&gt;The code loops 2e5 (i.e. 20,000) times and passes its variables by reference into a dummy function (to prevent the compiler optimizing the loop away).&lt;/p&gt;

&lt;p&gt;On my iPhone 3G, this runs between 5 and 6 frames per second.&lt;/p&gt;

&lt;h4&gt;Faster with tables&lt;/h4&gt;

&lt;p&gt;The reason this code is slow, is the &lt;code&gt;sinf()&lt;/code&gt; function &amp;mdash; the iPhone simply isn't meant for heavy floating point arithmetic.&lt;/p&gt;

&lt;p&gt;However, this code only uses 84 steps to get around the circle. We can precalculate all of those points, store them in a table and use the table instead.&lt;/p&gt;

&lt;pre&gt;static int tableIndexX = -1;
static int tableIndexY = 0;
if (tableIndexX == -1)
    tableIndexX = SinTableSize / 4;

for (int i = 0; i &lt; 2e5; i++)
{
    translateX = SinTable[tableIndexX];
    translateY = SinTable[tableIndexY];
    doNothingif(&amp;tableIndexX, &amp;translateX);
    doNothingif(&amp;tableIndexY, &amp;translateY);
}
tableIndexX = (tableIndexX + 1) % SinTableSize;
tableIndexY = (tableIndexY + 1) % SinTableSize;

glTranslatef((GLfloat)(translateX), (GLfloat)(translateY), 0.0f);&lt;/pre&gt;

&lt;p&gt;This code is the same as the previous code except instead of calculating each point, it simply steps through an array of values.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;SinTable&lt;/code&gt; just looks like this:&lt;/p&gt;

&lt;pre&gt;const float SinTable[84] = 
{
    0.000000f,
    0.037365f,
    0.074521f,
    0.111260f,
    //... 80 more entries ...
};&lt;/pre&gt;


&lt;p&gt;With the change to a lookup table, the code now runs at 26-28 frames per second. A 5 times speed increase.&lt;/p&gt;

&lt;h4&gt;Using code to generate code with a build rule&lt;/h4&gt;

&lt;p&gt;If you've ever used lookup tables, you'll know that they can be annoying to maintain. If you want to change them, you need to regenerate them and then reintegrate them into your project.&lt;/p&gt;

&lt;p&gt;With a custom build rule, the regeneration and reintegration can be done automatically.&lt;/p&gt;

&lt;p&gt;The code that generates the &lt;code&gt;SinTable&lt;/code&gt; looks like this:&lt;/p&gt;

&lt;pre&gt;enum
{
    ProcessName = 0,
    OutputFile,
    TableSteps,
    ArgumentCount
};

int main (int argc, const char * argv[])
{
    if (argc != ArgumentCount)
        return 1;
    
    FILE *outputFile = fopen(argv[OutputFile], "w");
    long tableSteps = strtol(argv[TableSteps], NULL, 10);
    
    fprintf(outputFile, "const float SinTable[%ld] = \n", tableSteps);
    fprintf(outputFile, "{\n");
    for (long i = 0; i &lt; tableSteps; i++)
    {
        fprintf(outputFile, "    %ff,\n", 0.5f * sinf(i * 2.0f * 3.14159265f / tableSteps));
    }
    fprintf(outputFile, "\n};\n");
    fprintf(outputFile, "const long SinTableSize = %ld;", tableSteps);
    
    return 0;
}&lt;/pre&gt;

&lt;p&gt;I put it in a file named SinTable.gen.c then I added a custom build rule to the target (Project&amp;rarr;Edit Active Target&amp;rarr;Rules).&lt;/p&gt;

&lt;p&gt;The custom build rule looks like this:&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/S2_gEsa6E_I/AAAAAAAAAls/bkeJNDsYLuk/buildrule.png?imgmax=800" alt="buildrule.png" border="0" width="499" height="326" /&gt;

&lt;p&gt;What this does is:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Takes any file that ends in .gen.c&lt;/li&gt;
&lt;li&gt;Compiles it to a .gen file in the Derived files directory&lt;/li&gt;
&lt;li&gt;Executes the .gen program to generate a gen.result.c file in the same directory&lt;/li&gt;
&lt;li&gt;Tells Xcode that it produces the gen.result.c file and Xcode will then build it according to Xcode's standard C compilation rules, integrating it with the rest of the program.&lt;/li&gt;&lt;/ol&gt;

&lt;h4&gt;Custom Build Rules versus Custom Build Phases&lt;/h4&gt;

&lt;p&gt;Many people are familiar with Custom Build Phases for running scripts during their builds. It is important to understand the differences between the two:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Custom Build Rule&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Run Script Custom Build Phase&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;Is an arbitrary /bin/sh script&lt;/td&gt;&lt;td&gt;Is an arbitrary /bin/sh script&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Runs once for input of a given type&lt;/td&gt;&lt;td&gt;Runs exactly once per build&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Only runs when an input of the relevant type changes&lt;/td&gt;&lt;td&gt;Runs on either every build (no inputs/outputs specified) or when specifically nominated "input" files are newer than nominated "output" files.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Outputs can be automatically picked up by Xcode for further processing by other build rules&lt;/td&gt;&lt;td&gt;Xcode doesn't touch outputs &amp;mdash; you must handle all processing yourself&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Only visible in the Target's Settings window&lt;/td&gt;&lt;td&gt;Visible in the Group Tree by expanding the Target&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Custom Build Rules are ideal for generating files that will be picked up by another build rule (for example, generating source code or .o files). Custom Build Phases are a better option for applying build numbers or handling the final built product.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;&lt;a href="http://projectswithlove.com/projects/Spinner.zip"&gt;Download the complete project for this post: Spinner.zip&lt;/a&gt; (25kb).&lt;/blockquote&gt;

&lt;p&gt;5 times faster, easy to implement and maintain.&lt;/p&gt;

&lt;p&gt;Of course, lookup tables have a major limitation: they use memory. This table was only 84 entries long, so there's no real problem but if you need thousands of entries, you'll need to test to make sure you're actually gaining performance. Also, if the table is never in cache (because you're using huge amounts of memory between lookups), you're unlikely to save much time.&lt;/p&gt;

&lt;p&gt;The point of this post though was to demonstrate build rules. This build rule keeps the lookup table up-to-date on every build and won't run unless the .gen.c file changes, so it won't recompile unnecessarily. The key strength of the build rule is that it will automatically run on all ".gen.c" files we happen to add to this target and the outputs are automatically picked up by Xcode and compiled and linked with the rest of the target.&lt;/p&gt;

&lt;p&gt;These two points are the key advantages of Build Rules in Xcode: running on every file of a given type and integration into the build pipeline. If you only need your script to run once per build (instead of once per file) and you don't need Xcode to further handle the outputs, you can use Run Script Custom Build Phases instead.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-6108577800484223211?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/IfNmh581zBs" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/6108577800484223211?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/6108577800484223211?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/IfNmh581zBs/custom-build-rules-generated-tables-and.html" title="Custom build rules, generated tables and faster floating point" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2010/02/custom-build-rules-generated-tables-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8GSXsyfyp7ImA9WxBWFEw.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-7708926989338139832</id><published>2010-02-01T03:34:00.001-08:00</published><updated>2010-02-05T15:50:28.597-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-05T15:50:28.597-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Xcode" /><category scheme="http://www.blogger.com/atom/ns#" term="performance tests" /><title>Finding the cause of performance issues in your programs</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;This post is a response to reader questions asking how, in my previous post on &lt;a href="http://cocoawithlove.com/2009/11/performance-tests-replacing-core-data.html"&gt;Replacing Core Data Key Paths&lt;/a&gt;, I knew that the biggest performance problem in my initial approach was the incremental reallocation of &lt;code&gt;NSMutableSet&lt;/code&gt;. In this post, I'll look at basic time and memory profiling on the Mac and talk about the most common types of scenario to look for when you're trying to solve performance problems.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In my previous post, &lt;a href="http://cocoawithlove.com/2009/11/performance-tests-replacing-core-data.html"&gt;Performance Tests: Replacing Core Data Key Paths&lt;/a&gt;, I presented a simple category to improve Core Data key path fetching by 25%-35% (actually the improvement was much greater at small set sizes but they rarely matter). The improvement worked by using property accessors to access the Core Data values instead of looking up the properties by string name.&lt;/p&gt;

&lt;p&gt;However, the original "na&amp;iuml;ve" approach that I used to do this actually took more than twice as long as the original Core Data string key paths.&lt;/p&gt;

&lt;p&gt;This week, I'll look at how I analyzed this code and how I worked out where the performance bottleneck was.&lt;/p&gt;

&lt;h4&gt;The code to analyze&lt;/h4&gt;

&lt;p&gt;The purpose of the code was to replace this:&lt;/p&gt;

&lt;pre&gt;NSSet *projectNames = [company valueForKeyPath:@"projects.name"];&lt;/pre&gt;

&lt;p&gt;with this:&lt;/p&gt;

&lt;pre&gt;NSSet *projectNames = [company.projects slowObjectValuesForProperty:@selector(name)];&lt;/pre&gt;

&lt;p&gt;But, as the "slow" in the method name reveals. The initial approach was slower &amp;mdash; by approximately a factor of 2.&lt;/p&gt;

&lt;p&gt;The implementation of the &lt;code&gt;slowObjectValuesForProperty:&lt;/code&gt; method is really simple. Let's look at it:&lt;/p&gt;

&lt;pre&gt;- (NSSet *)slowObjectValuesForProperty:(SEL)propertySelector
{
    NSMutableSet *result = [NSMutableSet set];
    for (id object in self)
    {
        id value = [object performSelector:propertySelector];
        if (value)
        {
            [result addObject:value];
        }
    }
    return result;
}&lt;/pre&gt;

&lt;p&gt;The test harness that I'll be using will be the &lt;a href="http://projectswithlove.com/projects/PropertyAccessors.zip"&gt;PropertyAccessors project&lt;/a&gt; from the &lt;a href="http://cocoawithlove.com/2009/11/performance-tests-replacing-core-data.html"&gt;Performance Tests: Replacing Core Data Key Paths&lt;/a&gt; post, with all tests except the "Key Path Accessor" and "slowObjectValuesForProperty: accessor" &lt;code&gt;ifdef&lt;/code&gt;'d out.&lt;/p&gt;

&lt;h4&gt;Time profiler&lt;/h4&gt;

&lt;p&gt;The first approach you should use when your code isn't running as fast as desired is a basic time profile.&lt;/p&gt;

&lt;p&gt;As preparation for this, you should make sure that the test will run for long enough to give useful test results. Time profiling works by suspending the program at regular intervals and reading the program's current position. This amounts to a random sampling over time. But these random samples won't be helpful unless there are enough in your time critical code. Increase your data size or put the code you're looking at in a loop and try to make it run for at least 2 seconds.&lt;/p&gt;

&lt;p&gt;For this test, I set the NumCompanies and NumProjectsPerCompany to 100 (giving a total data size of 10,000 project names) and further set the NumTestIterations to 1000 (so this test will fetch 10 million names in total).&lt;/p&gt;

&lt;p&gt;This gives the following test durations:&lt;/p&gt;

&lt;pre&gt;Key Path set iteration test took                4.13078 seconds.
Slow objectValuesForProperty: test took         8.83262 seconds.&lt;/pre&gt;

&lt;p&gt;By default, the Time Profiler will sample once every millisecond. If your tests cover a large amount of code, you'll need more samples &amp;mdash; so either make your tests run longer or increase the sample frequency (Time Profiler can go as fast as 20 &amp;mu;s).&lt;/p&gt;

&lt;p&gt;Build the project (but don't run it directly from Xcode). Then select the "Run&amp;rarr;Run with Performance Tool&amp;rarr;Time Profiler" menu. You can also use "Shark" for this but they both work in a similar way and the Time Profiler runs in Instruments which has a nicer, newer interface (although Shark can track a few lower level metrics that Instruments still lacks).&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;iPhone note:&lt;/strong&gt; The Time Profiler is not available to iPhone projects. For iPhone projects, select the "CPU Sampler" in the "Run with Performance Tool" menu. The "CPU Sampler" is higher overhead and cannot sample as often or as rigorously but will normally provide similar information.&lt;/blockquote&gt;

&lt;p&gt;The PropertyAccessors test will self-run, so you can just watch it go. For other projects where some interactivity may be required, you'll need to interact with the program until it runs the code you want to examine. If your test has a short duration or a large amount of code, you may need to click the "i" next to the "Time Profiler" Instruments icon at the top to change the sample rate to get good coverage for your program (you'll need to rerun the test if you make this change).&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/S2Z8gsjSFsI/AAAAAAAAAko/u16Sjso5XIs/instruments1.png?imgmax=800" alt="instruments1.png" border="0" width="500" height="386" /&gt;

&lt;p&gt;Your window should look like this. If it doesn't, make sure the "Detail" view is visible (you won't need the "Extended Detail" view). Also make sure the "Call Tree" view is selected in the "Detail" view (it's the icon at the bottom of the window that looks like three horizontal lines stacked slightly askew).&lt;/p&gt;

&lt;p&gt;Once the program finishes, uncheck the "Invert call tree" checkbox in the left column then expand the "Main Thread &amp;rarr; start &amp;rarr; &lt;code&gt;main&lt;/code&gt;" elements and we'll see the most expensive steps in the &lt;code&gt;main()&lt;/code&gt; function (which is where all the tests are run in this project).&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/S2aCFh8IlmI/AAAAAAAAAk0/KnTI8WqEDmg/instruments2.png?imgmax=800" alt="instruments2.png" border="0" width="500" height="87" /&gt;

&lt;p&gt;The top item in the &lt;code&gt;main()&lt;/code&gt; function is the &lt;code&gt;fetchObjectSetForRequest:&lt;/code&gt; method but we're not looking at that here (it's just Core Data loading and prefaulting the entire database).&lt;/p&gt;

&lt;p&gt;Instead, we want to know why the second item, &lt;code&gt;slowObjectValuesForProperty:&lt;/code&gt;, takes 2.23 times longer than the third item, &lt;code&gt;valueForKeyPath:&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Expanding the tree from the &lt;code&gt;slowObjectValuesForProperty:&lt;/code&gt; method twice, we see &lt;code&gt;CFBasicHashAddValue()&lt;/code&gt; occupies almost all of this method's time.&lt;/p&gt;

&lt;p&gt;If we expand the &lt;code&gt;valueForKeyPath:&lt;/code&gt; call tree 7 times, we can see the same &lt;code&gt;CFBasicHashAddValue()&lt;/code&gt; is used to create the set here but for some reason, this function only takes 1402 milliseconds here, compared to 5996 milliseconds for the &lt;code&gt;slowObjectValuesForProperty:&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;The same function, acting on the same data. But one takes 4 times longer than the other. What is the explanation?&lt;/p&gt;

&lt;p&gt;There are two possible answers: either the slow case is suffering from poor memory caching performance, or it is acting repeatedly and is slow due to repetition.&lt;/p&gt;

&lt;h4&gt;Object allocations&lt;/h4&gt;

&lt;p&gt;Shark can measure event counts (like cache misses and memory bandwidth) if you actually think that's the cause of a problem but it's unlikely to be the problem here. In most situations where the Time Profile isn't clear cut, the best thing to try here is a object allocation analysis.&lt;/p&gt;

&lt;p&gt;As with the Time Profile, we run the Object Allocations performance tool from "Run&amp;rarr;Run with Performance Tool&amp;rarr;Object Allocations" menu in Xcode.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/S2aMYX6R-jI/AAAAAAAAAk8/jsLBoGo2z3c/instruments3.png?imgmax=800" alt="instruments3.png" border="0" width="500" height="296" /&gt;

&lt;p&gt;Again, switch to the "Call Tree" view and make sure "Invert Call Tree" and "Separate by Category" are off.&lt;/p&gt;

&lt;p&gt;Additionally, right-click (or control click) in the table header of the "Detail" view and make certain that "Count" and "Bytes" columns are both enabled.&lt;/p&gt; 

&lt;p&gt;If you navigate into "Main Thread &amp;rarr; start &amp;rarr; &lt;code&gt;main&lt;/code&gt; &amp;rarr;&lt;code&gt;slowObjectValuesForProperty:&lt;/code&gt;", then follow the biggest allocation 4 times and you'll see that &lt;code&gt;__CFBasicHashRehash&lt;/code&gt; is responsible for allocating almost all of this method's memory.&lt;/p&gt;

&lt;p&gt;Similarly navigating into the &lt;code&gt;valueForKeyPath:&lt;/code&gt; of the other test, reveals the same method 7 levels in allocates a majority of this method's memory.&lt;/p&gt;

&lt;p&gt;However, there are three big differences between the memory performances of the &lt;code&gt;__CFBasicHashRehash&lt;/code&gt; in each case:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;The &lt;code&gt;slowObjectValuesForProperty:&lt;/code&gt; version performs 800,000 allocations whereas the &lt;code&gt;valueForKeyPath:&lt;/code&gt; version performs exactly 100,000 (equal to the number of tests).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;slowObjectValuesForProperty:&lt;/code&gt; version allocates 210.57MB whereas the &lt;code&gt;valueForKeyPath:&lt;/code&gt; version allocates just 97.66MB.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;slowObjectValuesForProperty:&lt;/code&gt; version is found inside &lt;code&gt;CFSetAddValue&lt;/code&gt; where the &lt;code&gt;valueForKeyPath:&lt;/code&gt; version is found inside &lt;code&gt;CFSetCreate&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From the first point, it would appear that the presumption that the slow version is slow because it unnecessarily repeats itself is looking accurate &amp;mdash; it is repeatedly reallocating.&lt;/p&gt;

&lt;p&gt;The second point also suggests that the slow method is wasting extra memory (which is probably causing mild performance penalities). On low memory systems, this would be even worse.&lt;/p&gt;

&lt;p&gt;The third point suggests why the first two might be the case: the slow method needs to reallocate as it adds more data.&lt;/p&gt;

&lt;h4&gt;Understand what the code you're invoking does&lt;/h4&gt;

&lt;p&gt;All this helps to identify where your program is spending its time. From here, you could probably work out that allocating the &lt;code&gt;NSMutableSet&lt;/code&gt; once, instead of repeatedly as you go, is a good idea.&lt;/p&gt;

&lt;p&gt;Of course, you need to confirm this by applying your changes and testing. Changing this code to allocate once instead of repeatedly as it goes is easy &amp;mdash; it takes a matter of seconds. You do need to be wary though about spending too long optimizing code on a whim. The more involved the code change, the more confident you should be that you're actually fixing a problem and not inspecting irrelevant code or making unhelpful changes.&lt;/p&gt;

&lt;p&gt;This is where it helps to really understand the code you're playing with.&lt;/p&gt;

&lt;p&gt;For example: the reason why moving to a single allocation with the &lt;code&gt;NSMutableSet&lt;/code&gt; above is helpful, is not actually directly because of the allocation itself &amp;mdash; since the biggest block of time inside &lt;code&gt;slowObjectValuesForProperty:&lt;/code&gt; that we're trying to optimize is spent in &lt;code&gt;__CFStringEqual&lt;/code&gt; and &lt;code&gt;memcmp&lt;/code&gt; when you drill all the way down; it is not spent in &lt;code&gt;malloc&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;Instead, I know that whenever &lt;code&gt;NSMutableSet&lt;/code&gt; resizes, it needs to rehash every single object back into the newly resized hash table. It is this rehashing that is hammering the &lt;code&gt;__CFStringEqual&lt;/code&gt; and &lt;code&gt;memcmp&lt;/code&gt; functions (since they are the functions used to hash and detect collisions in the hash table). Yes, reducing reallocations makes it faster but the biggest reason for this improvement is the nature of hashed storage: because reducing reallocations reduces the need to rehash.&lt;/p&gt;

&lt;p&gt;As I reported in the original post, fixing this allocation so that it happens just once will speed this code up by 2.6 times but it is important to understand that the need to rehash is why this change helped &amp;mdash; other reallocation situations may not gain as much as we have here.&lt;/p&gt;

&lt;h4&gt;Finding the best candidates for speed improvements&lt;/h4&gt;

&lt;p&gt;Generally though, allocations and reallocations are always a prime place to look. Large allocations are expensive to move around in RAM, millions of small, irregular allocations can fragment memory and every allocation normally needs to be initialized, incurring some kind of expense. Even with &lt;code&gt;NSArray&lt;/code&gt;, which doesn't need to rehash when it reallocates, there is still a copy of the elements from the old array to the new one. The performance gain will not be as great but it is still a place to squeeze extra performance.&lt;/p&gt;

&lt;p&gt;When optimizing, the first things to look for are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Memory allocations&lt;/strong&gt;. They're easy to find and easy to tweak. They don't always give the best performance improvements but they're a good first point to examine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Iteration over large arrays to find elements&lt;/strong&gt;. If you need to search large arrays often, you should be storing in a dictionary or other constant time access structure. Depending on the size of the array, this can be a near 100% speed improvement. i.e. never, ever search anything bigger than a trivial array.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nested loops over medium to large data sets&lt;/strong&gt;. Easy to find. Eliminate the nesting if you can. Although they can be hard to eliminate since you need to rethink how you access your data but you can often do something to reduce their impact. If you have 1 loop inside another, always put the smallest loop (in terms of number of elements) inside the bigger one if you can, since memory scales better to doing small packets of work huge numbers of times.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Anything non-polynomial on more than trivial data sets&lt;/strong&gt;. Non-polynomial actions are the slowest, worst things you can do. They are occasionally required but if at all possible, think up another design. What's non-polynomial? Anything where the number of packets of work involved in processing a collection grows greater than polynomially with respect to the size of the collection (i.e. if the packets of work are "y" and the number of objects in the collection is "x", then non-polynomial means the number of packets of work exceed y=x^a for large values of x, where a is any constant). Exponential growth (i.e. y=a^x) or factorial (i.e. y=x!) are the most common kinds of non-polynomial growth. If all this is confusing, then at least know the common case: trying to find an ordering or arrangement for a set of objects by exhaustively testing every combination is non-polynomial.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;You may be tempted to think that pervasive multi-threading, OpenCL, SSE vectorization or assembly optimizations are the best way to solve performance issues, since they are all "high performance" technologies and the fastest programs all use them in some combination. However, these technologies are much harder to implement than simple design improvements so they should always be something you consider once you're sure that the design can't be further improved.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;The first rule with optimization is that you should always optimize based on evidence.&lt;/p&gt;

&lt;p&gt;Don't begin to optimize if you can't find a bottleneck or create one with data. Optimizing without actual evidence of a bottleneck (just suspicion that there might be one in future) is called "&lt;a href="http://c2.com/cgi/wiki$?PrematureOptimization"&gt;Premature Optimization&lt;/a&gt;" and is normally considered a waste of time.&lt;/p&gt;

&lt;p&gt;However, even once you know where the bottleneck is, you need to know what is causing it. If the code is small, you can just play with it to see what happens but generally you need to inspect closely. It is surprisingly easy to make the wrong guesses about what is causing performance issues and waste time changing code for no gain.&lt;/p&gt;

&lt;p&gt;I hope I've shown you how to gather the information you need to understand simple performance problems and the types of clues you'll need to narrow down the locations in your code that can be improved.&lt;/p&gt;

&lt;/span&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-7708926989338139832?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/weHgWX-8Eow" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7708926989338139832?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7708926989338139832?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/weHgWX-8Eow/finding-cause-of-simple-performance.html" title="Finding the cause of performance issues in your programs" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2010/02/finding-cause-of-simple-performance.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IESHs-cCp7ImA9WxBXFEU.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-1828572426319888979</id><published>2010-01-25T20:51:00.001-08:00</published><updated>2010-01-25T20:51:49.558-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-25T20:51:49.558-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><title>5 key-value coding approaches in Cocoa</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Key-value coding (KVC) is a way of decoupling a generic action from the specific properties it may need to act upon. It is most commonly associated with the &lt;code&gt;NSKeyValueCoding&lt;/code&gt; protocol but there are a number of other ways to achieve the same effect. In this post, I look at why key-value coding is important and show you 5 different ways &amp;mdash; each with their own particular advantages &amp;mdash; to implement this pattern.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;NSKeyValueCoding&lt;/code&gt; protocol has been in Cocoa since Mac OS X 10.0 but it first made a real mark in Mac OS X 10.3 when user-interface bindings demonstrated their potential &amp;mdash; allowing user-interface controls to connect to properties on objects by configuring the data, not changing the code.&lt;/p&gt;

&lt;p&gt;While the core concepts in key-value coding exist (or can be implemented) in most programming frameworks, key-value coding is both prevalent and pervasive throughout Cocoa in a way that is uncommon, certainly among other compiled application frameworks.&lt;/p&gt;

&lt;p&gt;Despite its prevalence, you can avoid key-value coding if you choose. However, Apple introduced it for a reason &amp;mdash; it is a simple design pattern that can be highly beneficial to your code. To that end, I'm going to spend this post talking about what key-value coding is, how it can improve your code and different approaches you can use to achieve the effect.&lt;/p&gt;

&lt;h4&gt;What is key-value coding?&lt;/h4&gt;

&lt;p&gt;The idea behind key-value coding is pretty simple: instead of directly getting and setting specific properties on an object, key-value coding involves passing in a "key" (usually a string) and getting or setting the property associated with that key.&lt;/p&gt;

&lt;p&gt;This may sound a lot like &lt;code&gt;NSDictionary&lt;/code&gt;

&lt;p&gt;For example:
&lt;pre&gt;// Set a property directly...
someObject.someProperty = someValue;

// ...or set the same property using key-value coding
[someObject setValue:someValue forKey:@"someProperty"];&lt;/pre&gt;

&lt;p&gt;Why would you want to do this? The answer is that it decouples the action of setting a value for a property from the specific property involved.&lt;/p&gt;

&lt;p&gt;Imagine a table for editing names and addresses:&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/S15WkHl1zVI/AAAAAAAAAkU/4iaZ5Ht4-fU/tablescreenshot.png?imgmax=800" alt="tablescreenshot.png" border="0" width="251" height="155" /&gt;

&lt;p&gt;Without key-value coding, the &lt;code&gt;NSTableViewDataSource&lt;/code&gt; method to handle an edit for one of the rows might look like this:&lt;/p&gt;

&lt;pre&gt;- (void)tableView:(NSTableView *)aTableView
    setObjectValue:(NSString *)anObject
    forTableColumn:(NSTableColumn *)aTableColumn
    row:(int)rowIndex
{
    if ([[aTableColumn identifier] isEqual:@"name"])
    {
        [[records objectAtIndex:rowIndex] setName:anObject];
    }
    else if ([[aTableColumn identifier] isEqual:@"address"])
    {
        [[records objectAtIndex:rowIndex] setAddress:anObject];
    }
}&lt;/pre&gt;

&lt;p&gt;With key-value coding, the method becomes:&lt;/p&gt;

&lt;pre&gt;- (void)tableView:(NSTableView *)aTableView
    setObjectValue:(NSString *)anObject
    forTableColumn:(NSTableColumn *)aTableColumn
    row:(int)rowIndex
{
    [[records objectAtIndex:rowIndex] setValue:anObject forKey:[aTableColumn identifier]];
}&lt;/pre&gt;

&lt;p&gt;I spoke about bindings before: this approach isn't using user-interface bindings (that would require no code at all). This is really showing a simplified way that bindings might be implemented.&lt;/p&gt;

&lt;p&gt;This key-value coding approach is better because it doesn't have to handle the edit of each property as a separate condition. This is the essence of key-value coding.&lt;/p&gt;

&lt;p&gt;And key-value coding remains just as efficient as the data set increases in size. A table with 1,000 columns would require the same amount of code to edit.&lt;/p&gt;

&lt;h4&gt;KVC approach 1: NSKeyValueCoding protocol&lt;/h4&gt;

&lt;p&gt;All the key-value coding that I've show so far uses the &lt;code&gt;NSKeyValueCoding&lt;/code&gt; protocol. Actually, I call it a protocol but it is actually an "informal protocol" (a category on &lt;code&gt;NSObject&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This category implements the &lt;code&gt;setValue:forKey:&lt;/code&gt; and &lt;code&gt;valueForKey:&lt;/code&gt; methods that you can use for setting and getting values by &lt;code&gt;NSString&lt;/code&gt; keys.&lt;/p&gt;

&lt;h5&gt;Advantages&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Finds getter and setter methods automatically and will even get or set ivars directly if a getter or setter can't be found. This means that most properties automatically support &lt;code&gt;NSKeyValueCoding&lt;/code&gt;. Learn more about the search paths in my &lt;a href="http://cocoawithlove.com/2008/07/key-value-information.html"&gt;Key Value Information post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Includes key paths (for traversing multiple properties).&lt;/li&gt;
&lt;li&gt;Integrates with &lt;code&gt;NSKeyValueObserving&lt;/code&gt; for implementing the Observer design pattern.&lt;/li&gt;
&lt;li&gt;Offers fallbacks and ways of dealing with undefined keys.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Disadvantages&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;The extended search path makes this one of the slowest key-value coding approaches (see my earlier performance-related post on &lt;a href="http://cocoawithlove.com/2009/11/performance-tests-replacing-core-data.html"&gt;Replacing Core Data Key Paths&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Requires either a method or ivar on the class matching the property name that can be found by &lt;code&gt;NSKeyValueCoding&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Only supports &lt;code&gt;NSString&lt;/code&gt;s as property keys.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;KVC approach 2: Manual subsets of NSKeyValueCoding behavior&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;NSKeyValueCoding&lt;/code&gt; protocol looks up methods by selector names and looks up ivars by name.&lt;/p&gt;

&lt;p&gt;This is work that you can do yourself.&lt;/p&gt;

&lt;pre&gt;// Manual KVC setter method implementation
NSString *setterString = [@"set" stringByAppendingString:[someKeyString capitalizedString]];
[someObject performSelector:NSSelectorFromString(setterString) withObject:someValue];

// Manual KVC ivar setter
object_setInstanceVariable(someObject, someKeyString, someValue);&lt;/pre&gt;

&lt;p&gt;Why would you do this instead of using the &lt;code&gt;NSKeyValueCoding&lt;/code&gt; approach? You would only use this in situations where you want to avoid methods or ivars that would ordinarily be found by &lt;code&gt;NSKeyValueCoding&lt;/code&gt;. This approach allows you to define your own lookup path.&lt;/p&gt;

&lt;h5&gt;Advantages&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;More control over the lookup path than with &lt;code&gt;NSKeyValueCoding&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Potentially faster than &lt;code&gt;NSKeyValueCoding&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Will work for classes that don't inherit from &lt;code&gt;NSObject&lt;/code&gt; and hence don't have &lt;code&gt;NSKeyValueCoding&lt;/code&gt; implementations.&lt;/li&gt;
&lt;li&gt;Manual method implementations can get and set non-object values.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Disadvantages&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Less flexible than &lt;code&gt;NSKeyValueCoding&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In most cases, it is more work than using &lt;code&gt;NSKeyValueCoding&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;KVC approach 3: Associated objects&lt;/h4&gt;

&lt;p&gt;The Objective-C 2.0 runtime (used on the iPhone and 64-bit Mac OS X apps) allows you to set any object to be associated with any other object. This allows any object in the runtime to have an arbitrary set of extra properties set by key, without support from ivars or methods on the object itself.&lt;/p&gt;

&lt;pre&gt;objc_setAssociatedObject(someObject, someKey, someValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC);&lt;/pre&gt;

&lt;p&gt;The main reason why you would use this approach is that you want to set properties on an object from the outside &amp;mdash; i.e. without the object supporting, being involved with or even knowing about the property access. Properties can be set on an object by other parts of the program for their own purposes.&lt;/p&gt;

&lt;h5&gt;Advantages&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;No support from the object (methods or ivars) required.&lt;/li&gt;
&lt;li&gt;Key can be any pointer (so can the object if &lt;code&gt;OBJC_ASSOCIATION_ASSIGN&lt;/code&gt; is used).&lt;/li&gt;
&lt;li&gt;Potentially the fastest KVC approach.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Disadvantages&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Key is a pointer, not an object, so if an object is used, it must be a pointer-unique object (i.e. won't work if you try to get and set with different allocations of the same string value).&lt;/li&gt;
&lt;li&gt;Does not affect ivars or methods on the object. Generally this means if you want the object itself to know about the change, you must use a different approach.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;KVC approach 4: selectors as keys&lt;/h4&gt;

&lt;p&gt;Key-value coding is primarily about looking up a property for a key and then acting upon the property found during lookup.&lt;/p&gt;

&lt;p&gt;Objective-C has a lookup at its very core &amp;mdash; the method lookup. The keys for this lookup are selectors.&lt;/p&gt;

&lt;pre&gt;objc_msgSend(someObject, someSetterSelector, someValue);&lt;/pre&gt;

&lt;p&gt;This approach is similar to manually implementing the method part of &lt;code&gt;NSKeyValueCoding&lt;/code&gt; but rather than forming a selector string from the key and then looking up the selector string, this approach opts to use the selector as the key.&lt;/p&gt;

&lt;p&gt;The disadvantage this approach has is that separate selectors are needed for getting and setting.&lt;/p&gt;

&lt;h5&gt;Advantages&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Fastest approach that goes through methods (which is good since methods are overrideable and hence more subclass friendly).&lt;/li&gt;
&lt;li&gt;Can get and set non-object data (although &lt;code&gt;objc_msgSend_fpret&lt;/code&gt; and &lt;code&gt;objc_msgSend_stret&lt;/code&gt; need to be used to get &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;double&lt;/code&gt; and &lt;code&gt;struct&lt;/code&gt; properties).&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Disadvantages&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Different keys required for getting and setting.&lt;/li&gt;
&lt;li&gt;Selectors are not objects and are therefore can't be stored directly in Objective-C arrays and dictionaries (must use CoreFoundation or &lt;code&gt;NSValue&lt;/code&gt; wrappers).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;KVC approach 5: do it yourself&lt;/h4&gt;

&lt;p&gt;The final approach to key-value coding is to handle the implementation yourself. This is something you would do if you needed maximum flexibility (for handling unusual keys/values) or wanted to expose different key-value sets from a single object.&lt;/p&gt;

&lt;p&gt;The easiest way to do this is to expose a getter and a setter method and simply get or set the values on a dictionary contained by the object.&lt;/p&gt;

&lt;pre&gt;- (void)setCollectionValue:(id)value forKey:(NSString *)key
{
    [collectionDictionary setObject:value forKey:key];
}

- (id)getCollectionValueForKey:(NSString *)key
{
    return [collectionDictionary objectForKey:key];
}&lt;/pre&gt;

&lt;p&gt;To handle the internal storage of the values, you could use any of the key-value storage structures in Cocoa:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NSMutableDictionary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NSMapTable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CFMutableDictionaryRef&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;associated objects on &lt;code&gt;self&lt;/code&gt; or other objects (see above)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;or your own storage solution.&lt;/p&gt;

&lt;h5&gt;Advantages&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;A single object can exposes multiple, separate collections.&lt;/li&gt;
&lt;li&gt;Can get and set any data type supported by the underlying collection.&lt;/li&gt;
&lt;li&gt;The most flexible approach for fallbacks and handling special cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Disadvantages&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Must be implemented by the target class (will not work for arbitrary objects).&lt;/li&gt;
&lt;li&gt;Doesn't interoperate with &lt;code&gt;NSKeyValueObserving&lt;/code&gt; or any of the other &lt;code&gt;NSKeyValueCoding&lt;/code&gt; concepts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Using key-value coding is not mandatory &amp;mdash; it is certainly possible to implement whole projects without it. However, it is one of the best code patterns for reducing repetitious code and making classes more reusable by decoupling actions from properties and data.&lt;/p&gt;

&lt;p&gt;As you can see, there are a number of different kinds of key-value coding you can use in your program. &lt;code&gt;NSKeyValueCoding&lt;/code&gt; is probably the most flexible, reusable and best supported throughout Cocoa, so unless you need one of the advantages of the other approaches or you want to keep your solution to a problem narrow, it is probably the best approach to use.&lt;/p&gt; 

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-1828572426319888979?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/dkt5LMLuyYY" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1828572426319888979?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1828572426319888979?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/dkt5LMLuyYY/5-key-value-coding-approaches-in-cocoa.html" title="5 key-value coding approaches in Cocoa" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2010/01/5-key-value-coding-approaches-in-cocoa.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEBRng8eSp7ImA9WxBQGUk.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-8045767482856994267</id><published>2010-01-17T03:49:00.001-08:00</published><updated>2010-01-19T15:10:57.671-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-19T15:10:57.671-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><title>What is a meta-class in Objective-C?</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In this post, I look at one of the stranger concepts in Objective-C &amp;mdash; the meta-class. Every class in Objective-C has its own associated meta-class but since you rarely ever use a meta-class directly, they can remain enigmatic. I'll start by looking at how to create a class at runtime. By examining the "class pair" that this creates, I'll explain what the meta-class is and also cover the more general topic of what it means for data to be an object or a class in Objective-C.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Creating a class at runtime&lt;/h4&gt;
&lt;p&gt;The following code creates a new subclass of &lt;code&gt;NSError&lt;/code&gt; at runtime and adds one method to it:&lt;/p&gt;

&lt;pre&gt;Class newClass =
    objc_allocateClassPair([NSError class], "RuntimeErrorSubclass", 0);
class_addMethod(newClass, @selector(report), (IMP)ReportFunction, "v@:");
objc_registerClassPair(newClass);&lt;/pre&gt;

&lt;p&gt;The method added uses the function named &lt;code&gt;ReportFunction&lt;/code&gt; as its implementation, which is defined as follows:&lt;/p&gt;

&lt;pre&gt;void ReportFunction(id self, SEL _cmd)
{
    NSLog(@"This object is %p.", self);
    NSLog(@"Class is %@, and super is %@.", [self class], [self superclass]);
    
    Class currentClass = [self class];
    for (int i = 1; i &lt; 5; i++)
    {
        NSLog(@"Following the isa pointer %d times gives %p", i, currentClass);
        currentClass = object_getClass(currentClass);
    }

    NSLog(@"NSObject's class is %p", [NSObject class]);
    NSLog(@"NSObject's meta class is %p", object_getClass([NSObject class]));
}&lt;/pre&gt;

&lt;p&gt;On the surface, this is all pretty simple. Creating a class at runtime is just three easy steps:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Allocate storage for the "class pair" (using &lt;code&gt;objc_allocateClassPair&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Add methods and ivars to the class as needed (I've added one method using &lt;code&gt;class_addMethod&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Register the class so that it can be used (using &lt;code&gt;objc_registerClassPair&lt;/code&gt;).&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;However, the immediate question is: what is a "class pair"? The function &lt;code&gt;objc_allocateClassPair&lt;/code&gt; only returns one value: the class. Where is the other half of the pair?&lt;/p&gt;

&lt;p&gt;I'm sure you've guessed that the other half of the pair is the meta-class (it's the title of this post) but to explain what that is and why you need it, I'm going to give some background on objects and classes in Objective-C.&lt;/p&gt;

&lt;h4&gt;What is needed for a data structure to be an object?&lt;/h4&gt;

&lt;p&gt;Every object has a class. This is a fundamental object-oriented concept but in Objective-C, it is also a fundamental part of the data. Any data structure which has a pointer to a class in the right location can be treated as an object.&lt;/p&gt;

&lt;p&gt;In Objective-C, an object's class is determined by its &lt;code&gt;isa&lt;/code&gt; pointer. The &lt;code&gt;isa&lt;/code&gt; pointer points to the object's Class.&lt;/p&gt;

&lt;p&gt;In fact, the basic definition of an object in Objective-C looks like this:&lt;/p&gt;

&lt;pre&gt;typedef struct objc_object {
    Class isa;
} *id;&lt;/pre&gt;

&lt;p&gt;What this says is: any structure which starts with a pointer to a &lt;code&gt;Class&lt;/code&gt; structure can be treated as an &lt;code&gt;objc_object&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The most important feature of objects in Objective-C is that you can send messages to them:&lt;/p&gt;

&lt;pre&gt;[@"stringValue"
    writeToFile:@"/file.txt" atomically:YES encoding:NSUTF8StringEncoding error:NULL];&lt;/pre&gt;

&lt;p&gt;This works because when you send a message to an Objective-C object (like the &lt;code&gt;NSCFString&lt;/code&gt; here), the runtime follows object's &lt;code&gt;isa&lt;/code&gt; pointer to get to the object's &lt;code&gt;Class&lt;/code&gt; (the &lt;code&gt;NSCFString&lt;/code&gt; class in this case). The &lt;code&gt;Class&lt;/code&gt; then contains a list of the &lt;code&gt;Method&lt;/code&gt;s which apply to all objects of that &lt;code&gt;Class&lt;/code&gt; and a pointer to the &lt;code&gt;superclass&lt;/code&gt; to look up inherited methods. The runtime looks through the list of &lt;code&gt;Method&lt;/code&gt;s on the &lt;code&gt;Class&lt;/code&gt; and superclasses to find one that matches the message selector (in the above case, &lt;code&gt;writeToFile:atomically:encoding:error&lt;/code&gt; on &lt;code&gt;NSString&lt;/code&gt;). The runtime then invokes the function (&lt;code&gt;IMP&lt;/code&gt;) for that method.&lt;/p&gt;

&lt;p&gt;The important point is that the &lt;code&gt;Class&lt;/code&gt; defines the messages that you can send to an object.&lt;/p&gt;

&lt;h4&gt;What is a meta-class?&lt;/h4&gt;

&lt;p&gt;Now, as you probably already know, a &lt;code&gt;Class&lt;/code&gt; in Objective-C is also an object. This means that you can send messages to a &lt;code&gt;Class&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;NSStringEncoding defaultStringEncoding = [NSString defaultStringEncoding];&lt;/pre&gt;

&lt;p&gt;In this case, &lt;code&gt;defaultStringEncoding&lt;/code&gt; is sent to the &lt;code&gt;NSString&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;This works because every &lt;code&gt;Class&lt;/code&gt; in Objective-C is an object itself. This means that the &lt;code&gt;Class&lt;/code&gt; structure must start with an &lt;code&gt;isa&lt;/code&gt; pointer so that it is binary compatible with the &lt;code&gt;objc_object&lt;/code&gt; structure I showed above and the next field in the structure must be a pointer to the &lt;code&gt;superclass&lt;/code&gt; (or &lt;code&gt;nil&lt;/code&gt; for base classes).&lt;/p&gt;

&lt;p&gt;&lt;a href="http://cocoawithlove.com/2010/01/getting-subclasses-of-objective-c-class.html"&gt;As I showed last week&lt;/a&gt;, there are a couple different ways that a &lt;code&gt;Class&lt;/code&gt; can be defined, depending on the version of the runtime you are running, but yes, they all start with an &lt;code&gt;isa&lt;/code&gt; field followed by a &lt;code&gt;superclass&lt;/code&gt; field.&lt;/p&gt;

&lt;pre&gt;typedef struct objc_class *Class;
struct objc_class {
    Class isa;
    Class super_class;
    /* followed by runtime specific details... */
};&lt;/pre&gt;

&lt;p&gt;However, in order to let us invoke a method on a &lt;code&gt;Class&lt;/code&gt;, the &lt;code&gt;isa&lt;/code&gt; pointer of the &lt;code&gt;Class&lt;/code&gt; must itself point to a &lt;code&gt;Class&lt;/code&gt; structure and that &lt;code&gt;Class&lt;/code&gt; structure must contain the list of &lt;code&gt;Method&lt;/code&gt;s that we can invoke on the Class.&lt;/p&gt;

&lt;p&gt;This leads to the definition of a meta-class: the meta-class is the class for a &lt;code&gt;Class&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Simply put:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;When you send a message to an object, that message is looked up in the method list on the object's class.&lt;/li&gt;
&lt;li&gt;When you send a message to a class, that message is looked up in the method list on the class' meta-class.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The meta-class is essential because it stores the class methods for a &lt;code&gt;Class&lt;/code&gt;. There must be a unique meta-class for every &lt;code&gt;Class&lt;/code&gt; because every &lt;code&gt;Class&lt;/code&gt; has a potentially unique list of class methods.&lt;/p&gt;

&lt;h4&gt;What is the class of the meta-class?&lt;/h4&gt;

&lt;p&gt;The meta-class, like the &lt;code&gt;Class&lt;/code&gt; before it, is also an object. This means that you can invoke methods on it too. Naturally, this means that it must also have a class.&lt;/p&gt;

&lt;p&gt;All meta-classes use the base class' meta-class (the meta-class of the top &lt;code&gt;Class&lt;/code&gt; in their inheritance hierarchy) as their class. This means that for all classes that descend from &lt;code&gt;NSObject&lt;/code&gt; (most classes), the meta-class has the &lt;code&gt;NSObject&lt;/code&gt; meta-class as its class.&lt;/p&gt;

&lt;p&gt;Following the rule that all meta-classes use the base class' meta-class as their class, any base meta-classes will be its own class (their &lt;code&gt;isa&lt;/code&gt; pointer points to themselves). This means that the &lt;code&gt;isa&lt;/code&gt; pointer on the &lt;code&gt;NSObject&lt;/code&gt; meta-class points to itself (it is an instance of itself).&lt;/p&gt;

&lt;h4&gt;Inheritance for classes and meta-classes&lt;/h4&gt;

&lt;p&gt;In the same way that the &lt;code&gt;Class&lt;/code&gt; points to the superclass with its &lt;code&gt;super_class&lt;/code&gt; pointer, the meta-class points to the meta-class of the &lt;code&gt;Class&lt;/code&gt;' &lt;code&gt;super_class&lt;/code&gt; using its own &lt;code&gt;super_class&lt;/code&gt; pointer.&lt;/p&gt;

&lt;p&gt;As a further quirk, the base class' meta-class sets its &lt;code&gt;super_class&lt;/code&gt; to the base class itself.&lt;/p&gt;

&lt;p&gt;The result of this inheritance hierarchy is that all instances, classes and meta-classes in the hierarchy inherit from the hierarchy's base class.&lt;/p&gt;

&lt;p&gt;For all instances, classes and meta-classes in the &lt;code&gt;NSObject&lt;/code&gt; hierarchy, this means that all &lt;code&gt;NSObject&lt;/code&gt; instance methods are valid. For the classes and meta-classes, all &lt;code&gt;NSObject&lt;/code&gt; class methods are also valid.&lt;/p&gt;

&lt;p&gt;All this is pretty confusing in text. &lt;a href="http://www.sealiesoftware.com/blog/"&gt;Greg Parker&lt;/a&gt; has put together an &lt;a href="http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html"&gt;excellent diagram of instances, classes, meta-classes and their super classes&lt;/a&gt; and how they all fit together.&lt;/p&gt;

&lt;h4&gt;Experimental confirmation of this&lt;/h4&gt;

&lt;p&gt;To confirm all of this, let's look at the output of the &lt;code&gt;ReportFunction&lt;/code&gt; I gave at the start of this post. The purpose of this function is to follow the &lt;code&gt;isa&lt;/code&gt; pointers and log what it finds.&lt;/p&gt;

&lt;p&gt;To run the &lt;code&gt;ReportFunction&lt;/code&gt;, we need to create an instance of the dynamically created class and invoke the &lt;code&gt;report&lt;/code&gt; method on it.&lt;/p&gt;

&lt;pre&gt;id instanceOfNewClass =
    [[newClass alloc] initWithDomain:@"someDomain" code:0 userInfo:nil];
[instanceOfNewClass performSelector:@selector(report)];
[instanceOfNewClass release];&lt;/pre&gt;

&lt;p&gt;Since there is no declaration of the &lt;code&gt;report&lt;/code&gt; method, I invoke it using &lt;code&gt;performSelector:&lt;/code&gt; so the compiler doesn't give a warning.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ReportFunction&lt;/code&gt; will now traverse through the &lt;code&gt;isa&lt;/code&gt; pointers and tell us what objects are used as the class, meta-class and class of the meta-class.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Getting the class of an object:&lt;/strong&gt; the &lt;code&gt;ReportFunction&lt;/code&gt; uses &lt;code&gt;object_getClass&lt;/code&gt; to follow the &lt;code&gt;isa&lt;/code&gt; pointers because the &lt;code&gt;isa&lt;/code&gt; pointer is a protected member of the class (you can't directly access other object's &lt;code&gt;isa&lt;/code&gt; pointers). The &lt;code&gt;ReportFunction&lt;/code&gt; does not use the &lt;code&gt;class&lt;/code&gt; method to do this because invoking the &lt;code&gt;class&lt;/code&gt; method on a &lt;code&gt;Class&lt;/code&gt; object does not return the meta-class, it instead returns the &lt;code&gt;Class&lt;/code&gt; again (so &lt;code&gt;[NSString class]&lt;/code&gt; will return the &lt;code&gt;NSString&lt;/code&gt; class instead of the &lt;code&gt;NSString&lt;/code&gt; meta-class).&lt;/blockquote&gt;

&lt;p&gt;This is the output (minus &lt;code&gt;NSLog&lt;/code&gt; prefixes) when the program runs:&lt;/p&gt;

&lt;pre&gt;This object is 0x10010c810.
Class is RuntimeErrorSubclass, and super is NSError.
Following the isa pointer 1 times gives 0x10010c600
Following the isa pointer 2 times gives 0x10010c630
Following the isa pointer 3 times gives 0x7fff71038480
Following the isa pointer 4 times gives 0x7fff71038480
NSObject's class is 0x7fff710384a8
NSObject's meta class is 0x7fff71038480&lt;/pre&gt;

&lt;p&gt;Looking at the addresses reached by following the &lt;code&gt;isa&lt;/code&gt; value repeatedly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the object is address &lt;code&gt;0x10010c810&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;the class is address &lt;code&gt;0x10010c600&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;the meta-class is address &lt;code&gt;0x10010c630&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;the meta-class's class (i.e. the &lt;code&gt;NSObject&lt;/code&gt; meta-class) is address &lt;code&gt;0x7fff71038480&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;NSObject&lt;/code&gt; meta-class' class is itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The value of the addresses is not really important except that it shows the progress from class to meta-class to &lt;code&gt;NSObject&lt;/code&gt; meta-class as discussed.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;The meta-class is the class for a &lt;code&gt;Class&lt;/code&gt; object. Every &lt;code&gt;Class&lt;/code&gt; has its own unique meta-class (since every &lt;code&gt;Class&lt;/code&gt; can have its own unique list of methods). This means that all &lt;code&gt;Class&lt;/code&gt; objects are not themselves all of the same class.&lt;/p&gt;

&lt;p&gt;The meta-class will always ensure that the &lt;code&gt;Class&lt;/code&gt; object has all the instance &lt;em&gt;and&lt;/em&gt; class methods of the base class in the hierarchy, plus all of the class methods in-between. For classes descended from &lt;code&gt;NSObject&lt;/code&gt;, this means that all the &lt;code&gt;NSObject&lt;/code&gt; instance and protocol methods are defined for all &lt;code&gt;Class&lt;/code&gt; (and meta-class) objects.&lt;/p&gt;

&lt;p&gt;All meta-classes themselves use the base class' meta-class (&lt;code&gt;NSObject&lt;/code&gt; meta-class for &lt;code&gt;NSObject&lt;/code&gt; hierarchy classes) as their class, including the base level meta-class which is the only self-defining class in the runtime.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-8045767482856994267?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/dD4bsJSwHLM" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8045767482856994267?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8045767482856994267?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/dD4bsJSwHLM/what-is-meta-class-in-objective-c.html" title="What is a meta-class in Objective-C?" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MHSHY4eyp7ImA9WxBQEkQ.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-1995654764486174567</id><published>2010-01-11T19:35:00.001-08:00</published><updated>2010-01-12T04:30:39.833-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-12T04:30:39.833-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><title>Getting the subclasses of an Objective-C class</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Getting the full list of subclasses for a class is a fairly simple task but it requires some uncommon runtime functions which can make the process more difficult. In this post, I look at how a Class is defined in Objective-C and two completely different ways of working out the subclasses.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Given the high level of reflection and introspection in the Objective-C runtime, you might expect that you would simply find a &lt;code&gt;class_getSubclasses(Class parentClass)&lt;/code&gt; in the Objective-C Runtime API but no such function exists.&lt;/p&gt;

&lt;p&gt;There are a few possible reasons why this function might have been omitted &amp;mdash; dynamic class creation and loading, threading and locking concerns, historical omissions in the &lt;code&gt;class_t&lt;/code&gt; structure, premature optimization considerations or even an attempt to deliberately guide programmers away from certain designs &amp;mdash; but the result is that you must work out the subclasses for yourself.&lt;/p&gt;

&lt;p&gt;Note: fetching the subclasses of a class is an unusual thing to do and is usually done as an after-the-fact change to an API you don't control or as a debug-only introspection or hack. Generally, designs where subclasses explicitly register themselves work better than trying to find subclasses at runtime. For example, in my &lt;a href="http://cocoawithlove.com/2009/07/simple-extensible-http-server-in-cocoa.html"&gt;Simple, Extensible HTTP Server&lt;/a&gt;, every &lt;code&gt;HTTPResponseHandler&lt;/code&gt; must include:&lt;/p&gt;

&lt;pre&gt;+ (void)load
{
    [HTTPResponseHandler registerHandler:self];
}&lt;/pre&gt;

&lt;p&gt;which allows subclasses of &lt;code&gt;HTTPResponseHandler&lt;/code&gt; that "opt-in" to be discovered by the parent when it is looking for a handler to handle a request.&lt;/p&gt;

&lt;p&gt;Fetching subclasses is then used in situations where you can't include a &lt;code&gt;load&lt;/code&gt; method like this or you can justify not wanting to do this (e.g. debug-only verification code which checks that all &lt;code&gt;HTTPResponseHandlers&lt;/code&gt; you've written actually do register themselves).&lt;/p&gt;

&lt;h4&gt;Filter the list of all classes&lt;/h4&gt;

&lt;p&gt;The traditional definition of a class in Objective-C looks like this:&lt;/p&gt;

&lt;pre&gt;struct objc_class {
    Class isa;
    Class super_class;
    const char *name;
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;
    struct objc_method_list **methodLists;
    struct objc_cache *cache;
    struct objc_protocol_list *protocols;
};&lt;/pre&gt;

&lt;p&gt;Classes contain pointers to their superclass but contain no pointer to subclasses.&lt;/p&gt;

&lt;p&gt;Since there is no specific function to access the subclasses, the only approach using public APIs is to get the list of all classes in the runtime and test each one to see if it is a subclass of the class in question.&lt;/p&gt;

&lt;p&gt;If this sounds like a heavy-handed approach, you're probably right. In Mac OS X 10.6.2, there are 527 classes in Foundation alone and 1966 in the Cocoa framework. This doesn't include all the classes your project will add, plus classes in other frameworks. Of course, interrogating all of these only takes a millisecond or two but it's still not something you should do in a tight loop &amp;mdash; if you need to repeatedly use the list of subclasses for a class, you'll want to cache it somewhere.&lt;/p&gt;

&lt;p&gt;Fetching all the classes in the runtime is pretty simple:&lt;/p&gt;

&lt;pre&gt;int numClasses = objc_getClassList(NULL, 0);
Class *classes = NULL;

classes = malloc(sizeof(Class) * numClasses);
numClasses = objc_getClassList(classes, numClasses);

// do something with classes

free(classes);&lt;/pre&gt;

&lt;p&gt;The question is then: how do we determine which classes are actually subclasses of some parent class?&lt;/p&gt;

&lt;p&gt;The intuitive approach would be to use the &lt;code&gt;isSubclassOfClass:&lt;/code&gt; method:&lt;/p&gt;

&lt;pre&gt;NSMutableArray *result = [NSMutableArray array];
for (NSInteger i = 0; i &lt; numClasses; i++)
{
    if ([classes[i] isSubclassOfClass:parentClass])
    {
        [result addObject:classes[i]];
    }
}&lt;/pre&gt;

&lt;p&gt;Unfortunately, we can't do this because when considering all classes in the runtime, the method &lt;code&gt;isSubclassOfClass:&lt;/code&gt; may not be present on all of them (since &lt;code&gt;isSubclassOfClass:&lt;/code&gt; is an &lt;code&gt;NSObject&lt;/code&gt; method).&lt;/p&gt;

&lt;p&gt;The problem here is that many of the methods that are commonly considered to be implemented by all classes, are actually implemented by &lt;code&gt;NSObject&lt;/code&gt; or in an implementation of the &lt;code&gt;NSObject&lt;/code&gt; protocol. Some classes, like &lt;code&gt;_NSZombie_&lt;/code&gt; or &lt;code&gt;NSProxy&lt;/code&gt; don't derive from &lt;code&gt;NSObject&lt;/code&gt; and even if they do implement the &lt;code&gt;NSObject&lt;/code&gt; protocol, may do so in unpredictable ways (&lt;code&gt;_NSZombie_&lt;/code&gt; throws an exception for any method and &lt;code&gt;NSProxy&lt;/code&gt; forwards many of these methods to its target instead of responding for itself).&lt;/p&gt;

&lt;p&gt;So instead of invoking any methods on arbitrary classes we must use the runtime functions. We use &lt;code&gt;class_getSuperclass()&lt;/code&gt; to find out the class' superclass and compare this to the &lt;code&gt;parentClass&lt;/code&gt;. This gives the complete solution:&lt;/p&gt;

&lt;pre&gt;NSArray *ClassGetSubclasses(Class parentClass)
{
    int numClasses = objc_getClassList(NULL, 0);
    Class *classes = NULL;

    classes = malloc(sizeof(Class) * numClasses);
    numClasses = objc_getClassList(classes, numClasses);
    
    NSMutableArray *result = [NSMutableArray array];
    for (NSInteger i = 0; i &lt; numClasses; i++)
    {
        Class superClass = classes[i];
        do
        {
            superClass = class_getSuperclass(superClass);
        } while(superClass &amp;&amp; superClass != parentClass);
        
        if (superClass == nil)
        {
            continue;
        }
        
        [result addObject:classes[i]];
    }

    free(classes);
    
    return result;
}&lt;/pre&gt;

&lt;h4&gt;The fast and dirty hack approach&lt;/h4&gt;

&lt;p&gt;The function I just gave is the correct approach to use in a program. But I wouldn't feel like I'd made an interesting post if I didn't also show a completely different, totally unsafe approach too.&lt;/p&gt;

&lt;p&gt;This approach will require the Objective-C Runtime 2.0 (that's the one used in Mac OS X 64-bit and on the iPhone). In the new version of the runtime, a class actually contains a direct link to its subclasses.&lt;/p&gt;

&lt;p&gt;From &lt;a href="http://opensource.apple.com/source/objc4/objc4-437/runtime/objc-runtime-new.h"&gt;objc-runtime-new.h in Apple's opensource repository&lt;/a&gt;, a class is declared as follows:&lt;/p&gt;

&lt;pre&gt;typedef struct class_t {
    struct class_t *isa;
    struct class_t *superclass;
    Cache cache;
    IMP *vtable;
    class_rw_t *data;
} class_t;&lt;/pre&gt;

&lt;p&gt;with the &lt;code&gt;class_rw_t&lt;/code&gt; struct definition:&lt;/p&gt;

&lt;pre&gt;typedef struct class_rw_t {
    uint32_t flags;
    uint32_t version;

    const class_ro_t *ro;
    
    struct method_list_t **methods;
    struct chained_property_list *properties;
    struct protocol_list_t ** protocols;

    struct class_t *firstSubclass;
    struct class_t *nextSiblingClass;
} class_rw_t;&lt;/pre&gt;

&lt;p&gt;This means that we can traverse along the &lt;code&gt;firstSubclass&lt;/code&gt; and &lt;code&gt;nextSiblingClass&lt;/code&gt; members to reach all of the subclasses of a parent class without needing to read every class in the runtime.&lt;/p&gt;

&lt;p&gt;A depth-first recursive traversal then gives the full list of subclasses for a class:&lt;/p&gt;

&lt;pre&gt;typedef void *Cache;
#import "objc-runtime-new.h"

void AddSubclassesToArray(Class parentClass, NSMutableArray *subclasses)
{
    struct class_t *internalRep = (struct class_t *)parentClass;
    
    // Traverse depth first
    Class subclass = (Class)internalRep-&gt;data-&gt;firstSubclass;
    while (subclass)
    {
        [subclasses addObject:subclass];
        AddSubclassesToArray(subclass, subclasses);
    
        // Then traverse breadth-wise
        struct class_t *subclassInternalRep = (struct class_t *)subclass;
        subclass = (Class)subclassInternalRep-&gt;data-&gt;nextSiblingClass;
    }
}&lt;/pre&gt;

&lt;p&gt;However, while highly efficient compared to traversing the whole list of classes, this approach cannot be safely used. According to &lt;a href="http://opensource.apple.com/source/objc4/objc4-437/runtime/objc-runtime-new.m"&gt;objc-runtime-new.m&lt;/a&gt;, all access to the &lt;code&gt;data&lt;/code&gt; member of a &lt;code&gt;class_t&lt;/code&gt; must be protected by the &lt;code&gt;runtimeLock&lt;/code&gt; &amp;mdash; which is inaccessible outside the runtime library itself.&lt;/p&gt;

&lt;p&gt;Since the lock is inaccessible, it means that this approach cannot be made safe, since any thread (including threads automatically started by Cocoa) could cause you to crash.&lt;/p&gt;

&lt;p&gt;It was a fun experiment and I hope that Apple include a function to do this safely in the future.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;The runtime provides no simple method to access the subclasses of a class &amp;mdash; even in the newer version of the runtime where this data is actually stored in the class' data structure.&lt;/p&gt;

&lt;p&gt;Filtering out classes from the list of all classes presents some interesting problems due to the classes in the runtime which don't derive from &lt;code&gt;NSObject&lt;/code&gt;. Ultimately though, once you're aware of the limitations of using the full class list, getting subclasses is fairly simple.&lt;/p&gt;

&lt;p&gt;Even though it isn't data you normally need, it would be nice if Apple had decided to offer access to the subclass data in the new version of the runtime. It is more efficient and allows the list to be generated in sorted order if required.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-1995654764486174567?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/Gy8gXtS07Cs" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1995654764486174567?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1995654764486174567?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/Gy8gXtS07Cs/getting-subclasses-of-objective-c-class.html" title="Getting the subclasses of an Objective-C class" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2010/01/getting-subclasses-of-objective-c-class.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04HRXY6fip7ImA9WxBRF0U.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-4584199805380654280</id><published>2010-01-05T17:07:00.001-08:00</published><updated>2010-01-06T04:45:34.816-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-06T04:45:34.816-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="object-oriented design" /><title>Quality control in application development without unit testing</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In my last two posts, I've shown a &lt;a href="http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html"&gt;Mac app with full unit tests&lt;/a&gt; and an &lt;a href="http://cocoawithlove.com/2009/12/sample-iphone-application-with-complete.html"&gt;iPhone app with full unit tests&lt;/a&gt;. The reality though is that I do not write or test code this way. In this post, I look at why so few applications are actually developed using unit tests. I'll also look at the alternate approaches &amp;mdash; both manual and automated &amp;mdash; that are normally used to maintain high quality and low bug rates in application development.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Introduction&lt;/h4&gt;

&lt;p&gt;I have many friends who love unit tests. They never write code without writing the unit tests first. And they love it; the thought of writing code without unit tests seems foolish and scary to them. Test-first approaches ensure that they never write anything that isn't specified and unit tested.&lt;/p&gt;

&lt;p&gt;This post is not to dissuade these people from unit tests. If you already know that you know and love unit tests, then stick with them.&lt;/p&gt;

&lt;p&gt;But even unit testing advocates should remember that unit tests are about code-level specification and working within certain types of development methodology &amp;mdash; they do not attempt to catch all bugs.&lt;/p&gt;

&lt;p&gt;This post is primarily for people who have heard of unit tests and are wondering if they are an efficient way to maintain product quality and lower bug rates.&lt;/p&gt;

&lt;p&gt;The short answer is: no.  If you simply want to lower bug counts, the best and most efficient approach is through system tests.&lt;/p&gt;

&lt;h4&gt;Difficulties of unit testing for application development&lt;/h4&gt;

&lt;p&gt;Depending on your development methodology, unit tests can serve a number of different functions. But if used purely to detect bugs then they are a very high cost approach for low return.&lt;/p&gt;

&lt;p&gt;Unit tests don't test the overall program, only isolated units. This creates many holes (integration, timing, re-entrancy, inter-module communication) that need to be tested another way. These limitations are not unique to application development so I'll focus instead on something that is: the difficulty of isolating your units for testing.&lt;/p&gt;

&lt;p&gt;Advocates of unit testing claim that you can follow good program design and reduce coupling and integration, making tests easy to write.&lt;/p&gt;

&lt;p&gt;Unfortunately, in application development, that's not exactly possible.&lt;/p&gt;

&lt;p&gt;As I noted when I was &lt;a href="http://cocoawithlove.com/2009/12/design-of-iphone-application.html"&gt;discussing iPhone application design&lt;/a&gt;, the code that you write in a Cocoa application is mostly controller classes &amp;mdash; since the model and view classes are so reusable, you rarely need to write them yourself.&lt;/p&gt;

&lt;p&gt;Controller classes are the classes which link your program together &amp;mdash; they join model and view elements together to make your program. The entire purpose of these classes is coupling. The unit tests I wrote for the &lt;a href="http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html"&gt;WhereIsMyMac program&lt;/a&gt; were approximately three times the size of the original code due to large numbers of mock objects and tricky hackery to intercept calls into the Cocoa framework &amp;mdash; and this was a simple sample application, it could easily be much worse. Every mock object reduces the accuracy of the test by reducing the reality of the test environment and the risk of false positives or negatives in test results.&lt;/p&gt;

&lt;p&gt;Since controller classes are so common in applications and the main role of a controller class is to join different objects together, unit testing suffers from the following serious problems in application development:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Requires huge amounts of mocking code and other fakery (time consuming).&lt;/li&gt;
&lt;li&gt;The resulting tests are far removed from the integrated reality, making false positives and false negatives highly likely and leaving large holes that are simply not tested.&lt;/li&gt;&lt;/ul&gt;

&lt;h4&gt;System testing methodologies for application development&lt;/h4&gt;

&lt;p&gt;The best approach for testing an application is to accept the coupled, integrated, timing dependent, environment dependent nature and test everything in place. The idea is simple: test the complete program in the exact manner (or as close as possible) in which you expect it to be used.&lt;/p&gt;

&lt;p&gt;Tests which operate in this manner are classed as "&lt;a href="http://en.wikipedia.org/wiki/System_testing"&gt;system tests&lt;/a&gt;".&lt;/p&gt;

&lt;p&gt;The reason why system tests are the most efficient and accurate form of product testing is simple: if you want to ensure low bug rates for the user, test the program in the same way that the user will use it; don't test a fake environment and don't test at levels the user can't access.&lt;/p&gt;

&lt;h5&gt;Types of system testing&lt;/h5&gt;

&lt;p&gt;There are lots of ways to system test your code. In order from most important to least important for application development:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Sanity_test"&gt;Sanity testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/GUI_software_testing"&gt;User interface testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.logigear.com/newsletter/api_vs_unit.asp"&gt;API testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Regression_testing"&gt;Regression testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Performance_testing"&gt;Performance testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Load_testing"&gt;Load testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Scalability_testing"&gt;Scalability testing&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'm not going to give full definitions of these tests here &amp;mdash; I'm simply going to discuss their importance to applications and related projects. Follow the links to read more about each one.&lt;/p&gt;

&lt;p&gt;Every good application has point 2 and most have 3 and 4 as part of their regular testing methodology &amp;mdash; sanity checks occur as part of the development methodology (run your code before you commit) and fall outside formal testing.&lt;/p&gt;

&lt;p&gt;The important step in making system tests work is to keep them formalized.  If the test is not automated, then it should be formally documented so that each of the steps is correctly run during a testing phase. A basic or ad hoc approach to any of these points doesn't count though: proper quality comes from rigorous and clearly defined testing approaches.&lt;/p&gt;

&lt;h5&gt;User interface testing&lt;/h5&gt;

&lt;p&gt;User interface testing is normally performed using testing matrices. In its simplest form, this means a document containing all user interface test cases in a table &amp;mdash; a spreadsheet, workprocessor or TextEdit document, it doesn't really matter as long as it is documented.&lt;/p&gt;

&lt;p&gt;The rows in the table are all steps in operating your program (selecting menu items, operating buttons, perform edit operations). Every single user interface element in the program should be tested and most should be tested multiple ways to account for different expected effects.&lt;/p&gt;

&lt;p&gt;The columns are all environmental differences between runs. Different operating system versions, different computers, different installation settings or different builds of the application (lite, demo or full).&lt;/p&gt;

&lt;p&gt;Each cell in the table should then contain the observed result and an indication of whether this is a success or failure according to the specification.&lt;/p&gt;

&lt;p&gt;If you can automate the process, then great &amp;mdash; there are software tools that will help with this on the Mac. If you can't &amp;mdash; yes, user interface testing will get manual and tedious but ultimately, it is the only way to guarantee that the program works as expected. Most of the programs you use have simply had someone sitting in front of them, progressively clicking all the buttons and using all the controls &amp;mdash; for every test case in every version.&lt;/p&gt;

&lt;p&gt;You need to have the whole table documented and it needs to cover every element of the user interface. The purpose is to remind you to test everything (bad luck will ensure that failure to test a row will guarantee that it contains uncaught bugs).&lt;/p&gt;

&lt;h5&gt;API testing&lt;/h5&gt;

&lt;p&gt;In theory, user-interface testing should test everything in a user facing application. It may seem inefficient to suggest API testing (which is normally done for libraries and code modules).&lt;/p&gt;

&lt;p&gt;There are three reasons that any substantial application would want API tests:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Human testers of user-interfaces are lazy, forget or make mistakes&lt;/li&gt;
&lt;li&gt;API tests are automated and can be run at build-time or as part of continuous integration&lt;/li&gt;
&lt;li&gt;You can test issues that may not be obvious during user testing (like data coherency)&lt;/ul&gt;

&lt;p&gt;For user applications though, it presents the problem that you must create an API layer that can actually be programmatically tested. The common approach is to separate the "model" of your application into a separate module with an API layer.&lt;/p&gt;

&lt;p&gt;API testing is similar to unit testing in many respects:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;it is automated&lt;/li&gt;
&lt;li&gt;can be implemented using OCUnit or similar libraries&lt;/li&gt;
&lt;li&gt;can be used to develop your application using test-first methodologies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The difference is that API tests do not separate the units within the module. API tests test the whole module in-place, fully integrated. This means that the API tests can be quite removed from the implementation details &amp;mdash; which has the advantage that they can be more easily written by a separate programmer or test engineer, freeing up programming resources. API tests also aim to be optimally efficient: they only test inputs and outputs and don't care about how intermediary steps in the transformation occurs.&lt;/p&gt;

&lt;p&gt;API tests attempt to provide a realistic environment and data but do suffer from some of the same limitations as unit tests in that some parts of the environment must be synthetic (the full application will not be present during testing).&lt;/p&gt;

&lt;h5&gt;Regression tests&lt;/h5&gt;

&lt;p&gt;After you're happy that your program is working as intended, regression tests ensure that subsequent work doesn't screw it up.&lt;/p&gt;

&lt;p&gt;These are tests are normally used for programs that produce a file output. Their operation is basically: run the regression test and compare the output to the "known good" result which was saved previously. If the output changes unexpectedly, the test fails.&lt;/p&gt;

&lt;p&gt;For many file producing projects (like a few major open-source projects specializing in video codecs, PDF renderers, DVD authoring packages) this is the only test they include. However, it's all that these types of project require: a good set of regression tests should have high code coverage (exercise almost all of the program) and perform most of the work of API testing too.&lt;/p&gt;

&lt;p&gt;Regression tests can be human or automatically driven. Applescript can drive regression tests in full applications or OCUnit can be used to drive regression tests through an API layer.&lt;/p&gt;

&lt;h4&gt;Specification&lt;/h4&gt;

&lt;p&gt;As I hinted previously, there are a few roles served by unit tests that system tests handle. One is that unit tests are a form of specification for the code. You can use the tests as a way of learning what the code is supposed to do and in some cases for sketching out how future code should operate.&lt;/p&gt;

&lt;p&gt;API testing can certainly replicate the unit testing specification at the API level; again, API tests are like an interface optimized application of unit tests.&lt;/p&gt;

&lt;p&gt;However, I prefer the old-school approach: document your code with comments. Not with a line or two inside the method but full comment blocks on every single method documenting conditions on all parameters and the return parameters and effects of the method. Like test-first development, it is common to write comments first (specify the functionality of the method, then write it, asserting pre and post conditions if desired).&lt;/p&gt;

&lt;p&gt;I use a customized version of Xcode's "Script Menu&amp;rarr;HeaderDoc&amp;rarr;Insert @method comment" to automate the creation of the comment block's formatting from the method prototype.&lt;/p&gt;

&lt;p&gt;If the comments at the start of each method are not clear enough for documentation (think about Apple's Cocoa API documentation) then you're not doing your commenting job.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Unit testing an application is filled with difficulties and problems. In my development style, I consider the time cost of unit testing an application outweighs its benefits &amp;mdash; especially since a unit tested application still requires system tests like user-interface and regression tests for proper validation.&lt;/p&gt;

&lt;p&gt;Regardless of whether you use unit tests, formalized system testing &amp;mdash; either automated or manual and methodical &amp;mdash; is required to fully validate an application and ensure the lowest possible low bug rates.&lt;/p&gt;

&lt;p&gt;The most efficient approach is to test the interface that the program exposes in the exact way that the user will use it. For user interface apps, this means user testing matrices. For applications with a lot of model code, this means API tests. For document producing applications, this means regression tests. In many cases though, a combination of all three is best.&lt;/p&gt;

&lt;p&gt;Most of these approaches require that you be disciplined. You need to comment your code. You need to maintain user interface testing matrices. You need to refactor your model layer so it has an interface that can be tested automatically. You need to measure the code coverage of your regression tests.&lt;/p&gt;

&lt;p&gt;I know these things are tedious. I know that no one wants to write test plans, test documents and API tests. But if you love your program and you want it to suck less, this is work that needs to be done.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-4584199805380654280?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/vAA0FUT_YiQ" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/4584199805380654280?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/4584199805380654280?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/vAA0FUT_YiQ/high-quality-in-software-development.html" title="Quality control in application development without unit testing" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2010/01/high-quality-in-software-development.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8NSX46cCp7ImA9WxBQEkg.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-1442696364109675507</id><published>2009-12-27T15:59:00.001-08:00</published><updated>2010-01-11T15:51:38.018-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-11T15:51:38.018-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cocoa Touch" /><category scheme="http://www.blogger.com/atom/ns#" term="Xcode" /><category scheme="http://www.blogger.com/atom/ns#" term="UIKit" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="object-oriented design" /><title>A sample iPhone application with complete unit tests</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In this post, I present a complete Cocoa Touch iPhone application implemented with unit tests for all created code. I'll look at setting up build and debug targets and executables for both Application and Logic tests, and show you some of the differences between Application and Logic tests.&lt;/p&gt;

&lt;p&gt;The code for this post is an iPhone version of the &lt;a href="http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html"&gt;Mac post I presented last week&lt;/a&gt;.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Xcode unit testing targets for the iPhone&lt;/h4&gt;

&lt;p&gt;Like Mac unit testing, unit testing targets on the iPhone are generally divided into two types:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Logic tests&lt;/strong&gt; &amp;mdash; these are run in a executable that is separate from your application. The separate build can be easier to manage, faster to build and is easier to run objects in isolation since it avoids the application setup. However, you cannot test components which rely on the application (which is most user interface components). Generally, this type of test target is intended for libraries, frameworks and testing the back-end (model components of model-view-controller) of your application.&lt;p&gt;Logic tests are easily run at build-time or from the command-line, which is helpful for continuous integration or automated test processes.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Application tests&lt;/strong&gt; &amp;mdash; these tests let the application load first and are subsequently loaded into the existing application. This means that the full application environment is available to your tests. In many cases, controller tests and view tests need to be run as application tests since they are reliant on the full environment.&lt;p&gt;Application tests allow your application to be tested in a more realistic environment, reducing the chance that environment or integration level issues will be missed. They are normally run as a separate step (not as part of the build) and therefore may be less convenient for tests that need to be run every time.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;In last week's post on Mac development, I covered the Application Tests exclusively. For the iPhone, I will cover both. The reason for this is:&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;iPhone Application Tests will only run on the device&lt;/strong&gt;.&lt;/blockquote&gt;

&lt;p&gt;This is annoying. It means that you must have a device connected to your test machine via USB to run Application Tests and endure the slow copy-to-device and slow &lt;em&gt;gdb&lt;/em&gt; interaction speeds. Apple could have allowed the simulator to perform the same bundle injection but they have not.&lt;/p&gt;

&lt;p&gt;There are alternatives to this approach. You could probably run a regular iPhone application in the simulator and invoke SenTestingKit manually after your application starts. There's also Google's Toolbox for Mac has an &lt;a href="http://code.google.com/p/google-toolbox-for-mac/wiki/iPhoneUnitTesting"&gt;iPhone Unit Testing approach&lt;/a&gt; that runs in the simulator.&lt;/p&gt;

&lt;p&gt;But I'm going to keep to the default OCUnit approaches used in Xcode, so I'll show you how to configure both Application Tests and Logic Tests and I'll show you the sorts of tests that will run in both and which will require the full Application Test to run.&lt;/p&gt;

&lt;p&gt;To be clear: if you want to run Logic Tests for your &lt;em&gt;Mac&lt;/em&gt; applications, you can follow almost exactly the same approach that I present here. For Mac applications though, since you can invoke the ApplicationTests from the command line (as a post-build step or integration step) I would not normally consider the hassle of maintaining an extra build target and executable worth the effort.&lt;/p&gt;

&lt;h4&gt;iPhone project configuration&lt;/h4&gt;

&lt;h5&gt;Unit testing targets&lt;/h5&gt;

&lt;p&gt;After you've created a blank project, use the "Project&amp;rarr;New Target..." menu item to add two  new "Cocoa Touch&amp;rarr;Unit Testing Bundle" Targets to the project. These will be the &lt;em&gt;ApplicationTests&lt;/em&gt; and &lt;em&gt;LogicTests&lt;/em&gt; bundles.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Be wary of target memberships:&lt;/strong&gt; When you add bundle resources and sources-to-compile to the original project, also add these to the &lt;em&gt;LogicTests&lt;/em&gt; target but do not add them to the &lt;em&gt;ApplicationTests&lt;/em&gt; target. Testing-specific files should be added to the &lt;em&gt;LogicTests&lt;/em&gt; target and the &lt;em&gt;ApplicationTests&lt;/em&gt; target but not to the original project.&lt;/blockquote&gt;

&lt;p&gt;As with the Mac project configuration, that's sadly not enough to make it work.&lt;/p&gt;

&lt;p&gt;First, drag your original application's target onto the &lt;em&gt;ApplicationTests&lt;/em&gt; and &lt;em&gt;LogicTests&lt;/em&gt; targets to create a dependency (force the application to build before the unit tests).&lt;/p&gt;

&lt;p&gt;Then delete the Run Script phase of the &lt;em&gt;ApplicationTests&lt;/em&gt; testing target. It's only for logic tests and won't work for application tests.&lt;/p&gt;

&lt;p&gt;Then edit the &lt;em&gt;ApplicationTests&lt;/em&gt; target's settings (Right click&amp;rarr;Get Info) and set the "Build&amp;rarr;Linking&amp;rarr;Bundle Loader" for all configurations to:&lt;/p&gt;
&lt;pre&gt;$(CONFIGURATION_BUILD_DIR)/WhereIsMyPhone.app/WhereIsMyPhone&lt;/pre&gt;

&lt;p&gt;where "WhereIsMyPhone" is the name of the application you're unit testing. As with the Mac setup, this step lets the testing target link against the application (the &lt;em&gt;ApplicationTests&lt;/em&gt; target doesn't include the original source files and we don't want linker errors when compiling). Unlike the Mac setup, we don't need to set the "Unit Testing&amp;rarr;Test Host" (since we can't run using the build-time step).&lt;/p&gt;

&lt;p&gt;On the build configuration, also add &lt;code&gt;APPLICATION_TESTS&lt;/code&gt; to the "GCC 4.2 - Preprocessing&amp;rarr;Preprocessor Macros". This will let us flag certain tests for running in the &lt;em&gt;ApplicationTests&lt;/em&gt; bundle but not the &lt;em&gt;LogicTests&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It'd be nice to use the OCMock framework but the iPhone doesn't allow dynamic linking. Instead we need to take the OCMock source code from, &lt;a href="http://github.com/mmangino/OCMock"&gt;OCMock on GitHub&lt;/a&gt;, take the non-test-related files and add them directly to both unit testing targets' "Compile Sources" phases. To get it to compile for the iPhone you'll need to replace &lt;code&gt;isEqualTo:&lt;/code&gt; in &lt;code&gt;OCMConstraint.m&lt;/code&gt; with &lt;code&gt;isEqual:&lt;/code&gt;, the import of &lt;code&gt;&amp;lt;objc/objc-runtime.h&amp;gt;&lt;/code&gt; in &lt;code&gt;OCPartialMockObject.m&lt;/code&gt; with &lt;code&gt;&amp;lt;objc/runtime.h&amp;gt;&lt;/code&gt; and the &lt;code&gt;typeof&lt;/code&gt; in &lt;code&gt;OCMArg.h&lt;/code&gt; with &lt;code&gt;__typeof&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To ensure that the compiler will find the OCMock headers you will also need to add &lt;code&gt;$SRCROOT&lt;/code&gt; (non-recursive) to the Project Settings ("Project&amp;rarr;Edit Project Settings") under "Build&amp;rarr;Search Paths&amp;rarr;Header Search Paths" (for all Configurations).&lt;/p&gt;

&lt;h5&gt;Debugging setup for the ApplicationTests target&lt;/h5&gt;

&lt;p&gt;To run the application tests, we need to make a copy of the original iPhone application's target (Right Click&amp;rarr;Duplicate) &amp;mdash; give it a name like "WhereIsMyPhoneTesting" to distinguish from the original "WhereIsMyPhone" target.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Separate targets again:&lt;/strong&gt; You will need to keep the duplicate in sync with the original. This means that all source files and resources added to the application should also be added to the testing target.&lt;br/&gt;&lt;br/&gt;With all these separate targets, it's worth noting that you don't need to add to each target separately &amp;mdash; when you're adding a new file to the project, you are normally given the list of targets and you select the checkboxes for the appropriate targets all at once. Don't add test files to the application and don't add application files to the &lt;em&gt;ApplicationTests&lt;/em&gt; target and everything will work.&lt;/blockquote&gt;

&lt;p&gt;Drag the &lt;em&gt;ApplicationTests&lt;/em&gt; target onto this duplicate (to make the duplicate dependent on the application testing bundle). Also drag the application testing bundle (in the Group Tree under Products named &lt;em&gt;ApplicationTests.octest&lt;/em&gt;) to the new "WhereIsMyPhoneTesting" target's "Copy Bundle Resources" phase.&lt;/p&gt;

&lt;p&gt;Finally, in the settings for the "WhereIsMyPhoneTesting" target, for all Configurations set the "Build&amp;rarr;Packaging&amp;rarr;Product Name" to something distinct from the original target (e.g. change "WhereIsMyPhone" to "WhereIsMyPhoneTesting").&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;iPhone application tests only work on the device.&lt;/strong&gt;&lt;br/&gt;To run the iPhone's application unit tests, you must build and install onto a device. They will not load in the simulator. Yes, this is annoying. Please request simulator support for Application Tests in future iPhone SDK releases if this bothers you.&lt;/blockquote&gt;

&lt;p&gt;To set breakpoints and interactively debug, you'll need to build the &lt;em&gt;WhereIsMyPhoneTesting&lt;/em&gt; target before running the &lt;em&gt;WhereIsMyPhoneTesting&lt;/em&gt; executable on your device. If the project contains the custom executable (from the &lt;em&gt;LogicTests&lt;/em&gt; setup below) you may need to set the project's Executable (from the "Project&amp;rarr;Set Active Exectuable..." menu) to &lt;em&gt;WhereIsMyPhoneTesting&lt;/em&gt; manually.&lt;/p&gt;

&lt;h5&gt;Debugging setup for the LogicTests target&lt;/h5&gt;

&lt;p&gt;For the logic tests, we don't create another target but we do need to create a custom executable ("Project&amp;rarr;New Custom Executable...") named "&lt;em&gt;DebugLogicTests&lt;/em&gt;" or similar with a path relative to the Current SDK of:

&lt;pre&gt;Developer/usr/bin/otest&lt;/pre&gt;

&lt;p&gt;This is Apple's test harness and will handle the work of running the &lt;em&gt;LogicTests&lt;/em&gt; bundle headlessly in the iPhone Simulator.&lt;/p&gt;

&lt;p&gt;You also need to set the Arguments and Environment for this executable to work. Double click the &lt;em&gt;DebugLogicTests&lt;/em&gt; item in the Executables section of the Group Tree and edit the Arguments tab to look like this:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SzbtWoCSSbI/AAAAAAAAAjs/FzfVM1R9hm4/debuglogictests.png?imgmax=800" alt="debuglogictests.png" border="0" width="589" height="387" /&gt;

&lt;blockquote&gt;&lt;strong&gt;Warning:&lt;/strong&gt; order of arguments is important (the "-SenTest Self" must be first).&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you're in a hurry, the &lt;code&gt;DLYD_ROOT_PATH&lt;/code&gt; and &lt;code&gt;DYLD_FORCE_FLAT_NAMESPACE&lt;/code&gt; are normally enough to get it running. The rest relate to minor configuration points that you may want or need eventually but which aren't critical &amp;mdash; however, they may cause unexpected runtime behavior if missing.&lt;/blockquote&gt;

&lt;p&gt;To set breakpoints and interactively debug, you'll need to build the &lt;em&gt;LogicTests&lt;/em&gt; target before running the &lt;em&gt;DebugLogicTests&lt;/em&gt; executable in the simulator. Since the project contains a custom executable you may need to set the project's Executable (from the "Project&amp;rarr;Set Active Exectuable..." menu) to &lt;em&gt;DebugLogicTests&lt;/em&gt; first.&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/Sz_bPM5IAaI/AAAAAAAAAj4/oUsftsZa5Ik/projectconfig.png?imgmax=800" alt="projectconfig.png" border="0" width="501" height="173" /&gt;

&lt;p style="text-align:center;"&gt;&lt;em&gt;The project on the left is configured to run Application tests.&lt;br/&gt;The project on the right is configured to run Logic tests.&lt;br/&gt;Set Target and Executable to "WhereIsMyPhone" to run the application as normal.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you have tests running at build-time that fail but the actual compile has succeeded, you can Debug without rebuilding by pressing Command-Option-Return ("Run&amp;rarr;Debug").&lt;/p&gt;

&lt;h4&gt;The sample iPhone application&lt;/h4&gt;

&lt;p&gt;As with last week, the sample application is a recreation of my earlier post, &lt;a href="http://cocoawithlove.com/2009/09/whereismymac-snow-leopard-corelocation.html"&gt;WhereIsMyMac&lt;/a&gt;, this time written for the iPhone using a test-first approach to development.&lt;/p&gt;

&lt;p&gt;With so much discussion about how to set up the Xcode project, I might keep the discussion of the tests themselves quite brief. If you want to know more about the implementation of the tests, they are &lt;a href="http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html"&gt;almost identical to last week's&lt;/a&gt; &amp;mdash; I deliberately chose this application because the implementation is very similar on the Mac and iPhone &amp;mdash; so I encourage you to read through the writing of the tests from that post.&lt;/p&gt;

&lt;p&gt;The only significant differences between the iPhone and Mac applications are that the Window Controller from last week is a View Controller in the iPhone version, &lt;code&gt;NSTextField&lt;/code&gt;s are now &lt;code&gt;UILabel&lt;/code&gt;s and the &lt;code&gt;UIWebView&lt;/code&gt; that the iPhone version contains is simpler than the &lt;code&gt;WebView&lt;/code&gt; on the Mac, so the &lt;code&gt;mainFrame&lt;/code&gt; access never occurs on the iPhone.&lt;/p&gt;

&lt;h5&gt;There is no application for the LogicTests&lt;/h5&gt;

&lt;p&gt;What I'll focus on this time, are the differences between the Mac and iPhone tests and implementations. Here's an example:&lt;/p&gt;

&lt;pre&gt;#ifdef APPLICATION_TESTS

- (void)testAppDelegate
{
   id appDelegate = [[UIApplication sharedApplication] delegate];
   STAssertNotNil(appDelegate, @"Cannot find the application delegate.");
}

#endif&lt;/pre&gt;

&lt;p&gt;On the Mac, this code was almost the same (&lt;code&gt;NSApplication&lt;/code&gt; instead of &lt;code&gt;UIApplication&lt;/code&gt;). The big difference is that I've wrapped the entire test in &lt;code&gt;#ifdef APPLICATION_TESTS&lt;/code&gt; since the application delegate does not exist in the logic tests, we must ensure this test is only run for application tests (we added the &lt;code&gt;APPLICATION_TESTS&lt;/code&gt; preprocessor macro to the &lt;em&gt;ApplicationTests&lt;/em&gt; target only).&lt;/p&gt;

&lt;h5&gt;LogicTests are a different bundle	&lt;/h5&gt;

&lt;p&gt;The next big difference is that the actual application code, which runs out of the &lt;code&gt;mainBundle&lt;/code&gt; in the regular application, runs out of the &lt;em&gt;LogicTests.octest&lt;/em&gt; bundle that &lt;em&gt;otest&lt;/em&gt; loads in the &lt;em&gt;LogicTests&lt;/em&gt; target. To make code that accesses the bundle work the same, independent of where it is running, all &lt;code&gt;NSBundle&lt;/code&gt; access is handled by class.&lt;/p&gt;

&lt;p&gt;For example, the code in &lt;em&gt;WhereIsMyPhoneViewController.m&lt;/em&gt; that generates the HTML to send to the &lt;code&gt;UIWebView&lt;/code&gt; fetches the structure of the HTML from a file with:&lt;/p&gt;

&lt;pre&gt;[[NSBundle bundleForClass:[self class]]
    pathForResource:@"HTMLFormatString"
    ofType:@"html"]&lt;/pre&gt;

&lt;p&gt;Previously, I would have used &lt;code&gt;[NSBundle mainBundle]&lt;/code&gt; here but that code failed when run in the &lt;code&gt;LogicTests&lt;/code&gt;. The &lt;code&gt;[NSBundle bundleForClass:[self class]]&lt;/code&gt; will find the bundle that contains the class whether it is the main bundle or the &lt;em&gt;LogicTests.octest&lt;/em&gt; bundle loaded by &lt;em&gt;otest&lt;/em&gt;.&lt;/p&gt;

&lt;h5&gt;Many UIKit classes won't work without the UIApplication&lt;/h5&gt;

&lt;p&gt;Trying to add code to pass the tests in this project revealed that other tests would have to be conditionally excluded from &lt;em&gt;LogicTests&lt;/em&gt; as well:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;The default &lt;code&gt;loadView&lt;/code&gt; method will fail &amp;mdash; so the &lt;code&gt;testLoadView&lt;/code&gt; method is &lt;code&gt;#ifdef&lt;/code&gt;'d out.&lt;/li&gt;
&lt;li&gt;Any attempt to &lt;code&gt;alloc&lt;/code&gt;/&lt;code&gt;init&lt;/code&gt; a &lt;code&gt;UILabel&lt;/code&gt; will fail. I don't know why but because of this, all tests on the labels must be &lt;code&gt;#ifdef&lt;/code&gt;'d.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Generally, don't expect anything from the &lt;em&gt;UIKit&lt;/em&gt; framework to work in your Logic tests. Other frameworks will almost always work (in this application, the &lt;em&gt;CoreLocation&lt;/em&gt; and &lt;em&gt;Foundation&lt;/em&gt; frameworks work without issue).&lt;/p&gt;

&lt;p&gt;Within UIKit, some elements will work &amp;mdash; for example, &lt;code&gt;UIWebView&lt;/code&gt; didn't have any issues in my testing. Exactly which user-interface objects will fail in the &lt;em&gt;LogicTests&lt;/em&gt; bundle (without an actual running application) is never really clear until you try but these failures are why you still need to run the Application Tests to verify against &amp;mdash; the Application Tests are a more authoritative result for anything in &lt;code&gt;UIKit&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;Download the complete &lt;a href="http://projectswithlove.com/projects/WhereIsMyPhone-WithUnitTests.zip"&gt;WhereIsMyPhone-WithUnitTests.zip&lt;/a&gt; (85kb).
&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Warning:&lt;/strong&gt; custom executables (like the &lt;em&gt;DebugLogicTests&lt;/em&gt; executable) are &lt;em&gt;user&lt;/em&gt; data in the project file. This means that you will not see the &lt;em&gt;DebugLogicTests&lt;/em&gt; that I created in this project unless you create it yourself or your username happens to be "matt".
&lt;br/&gt;&lt;br/&gt;This project includes code from the &lt;a href="http://www.mulle-kybernetik.com/software/OCMock/"&gt;OCMock framework&lt;/a&gt;, which is Copyright (c) 2004-2009 by Mulle Kybernetik. OCMock is covered by its own license (contained in the &lt;em&gt;OCUnit/License.txt&lt;/em&gt; file in the download).&lt;/blockquote&gt;

&lt;p&gt;The code for this post is largely been a repeat of last week's post for the benefit of iPhone programmers. You can have a look at the differences for yourself but I deliberately chose this project because the iPhone and Mac implentations are so similar.&lt;/p&gt;

&lt;p&gt;I have taken the time though to show you how you can maintain a &lt;code&gt;LogicTests&lt;/code&gt; target (in addition to the application-wide &lt;em&gt;ApplicationTests&lt;/em&gt; target) that can test most of your project outside the application environment &amp;mdash; including most of the user-interface controller code. The purpose is to sidestep the "device-only" limitations of the current &lt;code&gt;OCUnit&lt;/code&gt; testing for the iPhone but also to show how you could set up build-time unit tests for &lt;em&gt;part&lt;/em&gt; of your application, without necessarily applying this approach to your entire project.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-1442696364109675507?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/wFn0mc3gJiM" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1442696364109675507?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1442696364109675507?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/wFn0mc3gJiM/sample-iphone-application-with-complete.html" title="A sample iPhone application with complete unit tests" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/12/sample-iphone-application-with-complete.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QHRn08cSp7ImA9WxBWFU8.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-1348926749963474151</id><published>2009-12-21T15:40:00.001-08:00</published><updated>2010-02-06T22:48:57.379-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-06T22:48:57.379-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Xcode" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="object-oriented design" /><category scheme="http://www.blogger.com/atom/ns#" term="AppKit" /><title>A sample Mac application with complete unit tests</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In this post, I present a complete Cocoa Mac application implemented with unit tests for all created code. I'll create the tests first and then only add the code required to make the tests pass, largely following a test-driven development (TDD) methodology.&lt;/p&gt;

&lt;p&gt;Next week I'll show the configuration and implementation of this project as an iPhone application for the benefit of Cocoa Touch developers.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Introduction&lt;/h4&gt;

&lt;p&gt;A few days ago, I spent some time searching for a Cocoa application with source code and full unit tests but I was only able to find Apple's trivial &lt;a href="http://developer.apple.com/IPhone/library/samplecode/iPhoneUnitTests/index.html"&gt;iPhoneUnitTests sample project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With more than four years of official support (Apple added OCUnit to the Developer Tools in 2005) and a large number of articles and blog posts by Mac programmers endorsing unit testing and offering solutions to problems within unit testing, it is surprising to me that there are so few code examples showing Cocoa applications with full unit tests.&lt;/p&gt;

&lt;p&gt;So I decided to re-implement one of my own projects (&lt;a href="http://cocoawithlove.com/2009/09/whereismymac-snow-leopard-corelocation.html"&gt;the WhereIsMyMac application from an earlier post&lt;/a&gt;) with complete unit tests using a test-first approach &amp;mdash; I'll create failing tests and only add code to the project to pass those failing tests.&lt;/p&gt;

&lt;p&gt;I'll be cheating a bit relative to proper test-first development (since this is a re-implementation of an existing project, I already know what the final code should be) but I'll keep to the spirit of the process by only adding as much code as I need to make the tests pass.&lt;/p&gt;

&lt;p&gt;I know people will want to see how this works on the iPhone but since this post is already large, I've deferred that implementation until next week.&lt;/p&gt;

&lt;h4&gt;Xcode unit testing targets&lt;/h4&gt;

&lt;p&gt;There are two different ways of configuring Xcode for unit testing: logic test targets and application test targets.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Logic tests&lt;/strong&gt; &amp;mdash; these are run in a executable that is separate from your application. The separate build can be easier to manage, faster to build and is easier to run objects in isolation since it avoids the application setup. However, you cannot test components which rely on the application (which is most user interface components). Generally, this type of test target is intended for libraries, frameworks and testing the back-end (model components of model-view-controller) of your application.&lt;p&gt;Logic tests are easily run at build-time or from the command-line, which is helpful for continuous integration or automated test processes.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Application tests&lt;/strong&gt; &amp;mdash; these tests let the application load first and are subsequently loaded into the existing application. This means that the full application environment is available to your tests. In many cases, controller tests and view tests need to be run as application tests since they are reliant on the full environment.&lt;p&gt;Application tests allow your application to be tested in a more realistic environment, reducing the chance that environment or integration level issues will be missed. They are normally run as a separate step (not as part of the build) and therefore may be less convenient for tests that need to be run every time.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;I'll focus exclusively on the second type of testing target, since it will allow full testing of the application.&lt;/p&gt;

&lt;p&gt;It may seem strange to talk about "unit tests" which are supposed to be run in isolation but then talk about "Application tests" which provide the environment in which to run tests. The reality is that you can only isolate user-interface unit tests from your own code &amp;mdash; there will always be some interaction (in hidden and not controllable ways) with the application framework code. Windows, views and controls simply won't work if there's no application around them.&lt;/p&gt;

&lt;h4&gt;Mac project configuration&lt;/h4&gt;

&lt;p&gt;One of the best sources of information on configuring Xcode for Unit Tests is &lt;a href="http://chanson.livejournal.com/119097.html"&gt;Chris Hanson's series on unit testing&lt;/a&gt;. I'll follow many of the steps that he describes and further add OCMock integration to the procedure.&lt;/p&gt;

&lt;p&gt;After you've created a blank project, use the "Project&amp;rarr;New Target..." menu item to add a new "Cocoa&amp;rarr;Unit Testing Bundle" Target to the project.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Note:&lt;/strong&gt; The testing target is a separate target. This means that you need to be careful of target membership. All application source files should be added to the application target only. Test code files should be added to the testing target only.&lt;/blockquote&gt;

&lt;p&gt;It'd be great if that's all that you needed but there's more.&lt;/p&gt;

&lt;p&gt;First, drag your application's target onto the unit testing target to create a dependency (force the application to build before the unit tests).&lt;/p&gt;

&lt;p&gt;Then edit the unit testing target's settings (Right click&amp;rarr;Get Info) and set the "Build&amp;rarr;Linking&amp;rarr;Bundle Loader" for all configurations to:&lt;/p&gt;
&lt;pre&gt;$(CONFIGURATION_BUILD_DIR)/WhereIsMyMac.app/Contents/MacOS/WhereIsMyMac&lt;/pre&gt;

&lt;p&gt;where "WhereIsMyMac" is the name of the application you're unit testing. This will let the testing target link against the application (so you don't get linker errors when compiling).&lt;/p&gt;

&lt;p&gt;Also set the "Build&amp;rarr;Unit Testing&amp;rarr;Test Host" to &lt;code&gt;$(BUNDLE_LOADER)&lt;/code&gt; (this will give this property the same value as the above setting). This property lets the automated build-time script know to launch the application and inject the unit testing bundle into it to start the tests.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Logic tests note:&lt;/strong&gt; If you want to do logic tests instead of application tests, leave the Bundle Loader and Test Host fields empty and add all files you want to test to the test target (so the test target becomes a separate, self-contained target instead of linking against the main application).&lt;/blockquote&gt;

&lt;p&gt;Finally, &lt;a href="http://www.mulle-kybernetik.com/software/OCMock/"&gt;download a copy of OCMock&lt;/a&gt;, place the OCMock.framework in the same directory as your .xcodeproj file and set the "Build&amp;rarr;Search Paths&amp;rarr;Framework Search Paths" to:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;code&gt;"$(SDKROOT/Developer/Library/Frameworks"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;"$(SRCROOT)"&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Neither need to be recursive. The quotes are to handle potential spaces in your paths. The first search path will probably already exist in the settings but we add the second search path so that the OCUnit framework will be found in the project's directory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The configuration so far will run all tests as a build step (the Cocoa Unit Testing target includes a Run Script build step that runs all the unit tests).&lt;/p&gt;

&lt;p&gt;To allow debugging as well as build-time execution, add a new executable to the project ("Project&amp;rarr;New Custom Executable...") with a path relative to the Build Product of:&lt;/p&gt;

&lt;pre&gt;WhereIsMyMac.app/Contents/MacOS/WhereIsMyMac&lt;/pre&gt;

&lt;p&gt;and in the custom application's settings (Right click&amp;rarr;Get Info) on the Argument tab, set the arguments and environment variables as follows:&lt;/p&gt;

&lt;div style="width=100%;overflow:scroll;"&gt;&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/Sy83h8FLjTI/AAAAAAAAAjc/6KUZNWwTU6o/executable_settings.png" alt="executable_settings.png" border="0" width="844" height="304" /&gt;&lt;/div&gt;

&lt;p&gt;Most of these settings configure the application to load our test bundle into itself when it runs. The &lt;code&gt;:$(SRCROOT)&lt;/code&gt; at the end of fallback framework path is to allow the application to find the OCUnit framework in our project directory at runtime.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Separate executable&lt;/strong&gt;: since this test debugging executable is a separate executable, you will need to switch to the debugging executable for debugging tests and switch back when you want to run the application normally.&lt;/blockquote&gt;

&lt;h4&gt;AppDelegate Tests&lt;/h4&gt;

&lt;h5&gt;Startup integration&lt;/h5&gt;

&lt;p&gt;The application will start with the &lt;code&gt;WhereIsMyMacAppDelegate&lt;/code&gt; and we'll use the the &lt;code&gt;WhereIsMyMacAppDelegate&lt;/code&gt; to load the main window.&lt;/p&gt;

&lt;p&gt;The first test is therefore to ensure that application's delegate is an instance of &lt;code&gt;WhereIsMyMacAppDelegate&lt;/code&gt; on startup.&lt;/p&gt;

&lt;pre&gt;- (void)testAppDelegate
{
    id appDelegate = [[NSApplication sharedApplication] delegate];
    STAssertTrue([appDelegate isKindOfClass:[WhereIsMyMacAppDelegate class]],
        @"Cannot find the application delegate.");
}&lt;/pre&gt;

&lt;p&gt;This is a short and simple test but it isn't a unit test. It's actually an integration test (since it is testing the fully connected &lt;code&gt;+[NSApplication sharedApplication]&lt;/code&gt; in place.&lt;/p&gt;

&lt;p&gt;An ideal unit test would test the &lt;code&gt;NSApplication&lt;/code&gt; in isolation and ensure that it creates and sets its delegate property correctly. This is infeasible since &lt;code&gt;NSApplication&lt;/code&gt; can't be isolated so we simply accept the nature of the class and test the instance of &lt;code&gt;sharedApplication&lt;/code&gt; that should be created on startup. Of course, unit testing &lt;code&gt;NSApplication&lt;/code&gt; itself shouldn't be necessary but an integration test to ensure that the startup of the program leads correctly to the creation and setting of the &lt;code&gt;WhereIsMyMacAppDelegate&lt;/code&gt; is still a good idea.&lt;/p&gt;

&lt;h5&gt;applicationDidFinishLaunching:&lt;/h5&gt;

&lt;p&gt;The next test is to ensure that &lt;code&gt;applicationDidFinishLaunching:&lt;/code&gt; on the delegate will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create the &lt;code&gt;WhereIsMyMacWindowController&lt;/code&gt; and set it on the delegate&lt;/li&gt;
&lt;li&gt;load the &lt;code&gt;WhereIsMyMacWindowController&lt;/code&gt;'s window&lt;/li&gt;
&lt;li&gt;make the &lt;code&gt;WhereIsMyMacWindowController&lt;/code&gt;'s window the main and key window&lt;/li&gt;
&lt;/ol&gt;

&lt;pre&gt;- (void)testApplicationDidFinishLaunching
{
    WhereIsMyMacAppDelegate *appDelegate =
        [[[WhereIsMyMacAppDelegate alloc] init] autorelease];

    id mockWindow = [OCMockObject mockForClass:[NSWindow class]];
    [[mockWindow expect] makeKeyAndOrderFront:appDelegate];

    mockWindowController = [OCMockObject mockForClass:[WhereIsMyMacWindowController class]];
    [[[mockWindowController expect] andReturn:mockWindow] window];
    NSUInteger preRetainCount = [mockWindowController retainCount];

    [appDelegate applicationDidFinishLaunching:nil];
    
    [mockWindowController verify];
    [mockWindow verify];
    
    NSUInteger postRetainCount = [mockWindowController retainCount];
    STAssertEquals(postRetainCount, preRetainCount + 1, @"Window controller not retained");

    id windowController;
    object_getInstanceVariable(appDelegate, "windowController", (void **)&amp;windowController);
    STAssertEqualObjects(windowController, mockWindowController,
        @"windowController not set on appDelegate");

    object_setInstanceVariable(appDelegate, "windowController", nil);
    mockWindowController = nil;
}&lt;/pre&gt;

&lt;p&gt;This test is a near perfectly decoupled unit test of the &lt;code&gt;-[WhereIsMyMacAppDelegate applicationDidFinishLaunching:]&lt;/code&gt; method. However, the approaches used to decouple it from the rest of the program probably make it tricky to understand.&lt;/p&gt;

&lt;p&gt;The first two lines create a clean &lt;code&gt;WhereIsMyMacAppDelegate&lt;/code&gt; to test.&lt;/p&gt;

&lt;p&gt;The second two lines create a mock &lt;code&gt;NSWindow&lt;/code&gt; that we use to check that the window is brought to the front by &lt;code&gt;makeKeyAndOrderFront:&lt;/code&gt;. In conjunction with the later &lt;code&gt;[mockWindow verify]&lt;/code&gt; this will test the 3rd requirement in the list above.&lt;/p&gt;

&lt;p&gt;The next three lines create a &lt;code&gt;WhereIsMyMacWindowController&lt;/code&gt; that will be swapped in place of any &lt;code&gt;WhereIsMyMacWindowController&lt;/code&gt; that the &lt;code&gt;appDelegate&lt;/code&gt; tries to create (more on how this works in the next paragraph). The &lt;code&gt;mockWindowController&lt;/code&gt; is told to expect &lt;code&gt;window&lt;/code&gt; to be invoked and when it does, will return the &lt;code&gt;mockWindow&lt;/code&gt;. In conjunction with the &lt;code&gt;[mockWindowController verify]&lt;/code&gt;, the retain count checks and the &lt;code&gt;STAssertEqualObjects&lt;/code&gt; will verify the first two requirements in the list.&lt;/p&gt;

&lt;p&gt;I mentioned that &lt;code&gt;mockWindowController&lt;/code&gt; will be substituted in place of a real &lt;code&gt;WhereIsMyMacWindowController&lt;/code&gt; any time the &lt;code&gt;appDelegate&lt;/code&gt; tries to create a &lt;code&gt;WhereIsMyMacWindowController&lt;/code&gt;. This works because &lt;code&gt;mockWindowController&lt;/code&gt; is a global variable that affects the following category:&lt;/p&gt; 

&lt;pre&gt;id mockWindowController = nil;

@implementation WhereIsMyMacWindowController (WhereIsMyMacAppDelegateTests)

- (id)init
{
    if (mockWindowController)
    {
        [self release];
        return mockWindowController;
    }
    
    return invokeSupersequent();
}

@end&lt;/pre&gt;

&lt;p&gt;This category overrides the &lt;code&gt;-[WhereIsMyMacWindowController init]&lt;/code&gt; method to return the &lt;code&gt;mockWindowController&lt;/code&gt; if it exists, otherwise the default behavior. The &lt;code&gt;invokeSupersequent()&lt;/code&gt; comes from my old &lt;a href="http://cocoawithlove.com/2008/03/supersequent-implementation.html"&gt;Supersequent implementation&lt;/a&gt; post (it's like invoking the &lt;code&gt;super&lt;/code&gt; method but will invoke the current class' base or earlier category implementation, not just a genuine &lt;code&gt;super&lt;/code&gt; method and is more flexible &amp;mdash; though slower &amp;mdash; than method swizzling).&lt;/p&gt;

&lt;p&gt;Of course, we only want this override to return the mock object at specific times. This is why the &lt;code&gt;mockWindowController&lt;/code&gt; must be explicitly set back to &lt;code&gt;nil&lt;/code&gt; at the end of the method.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Notice that the category overrides init, not alloc:&lt;/strong&gt; technically, overriding &lt;code&gt;alloc&lt;/code&gt; would prevent any method being invoked on &lt;code&gt;WhereIsMyMacWindowController&lt;/code&gt; (making the test perfectly decoupled from other classes) however this would mean that we'd need to invoke &lt;code&gt;init&lt;/code&gt; on the mock object and &lt;code&gt;OCClassMockObject&lt;/code&gt; does not let you mock any methods that it implements for itself (this includes all of the &lt;code&gt;NSProxy&lt;/code&gt; methods plus &lt;code&gt;initWithClass:&lt;/code&gt; and &lt;code&gt;mockedClass&lt;/code&gt;). So instead, we override &lt;code&gt;init&lt;/code&gt; and make the acceptable tradeoff to allow &lt;code&gt;+[WhereIsMyMacWindowController alloc]&lt;/code&gt; to be invoked.&lt;br/&gt;&lt;br/&gt;A related point is that &lt;code&gt;OCClassMockObject&lt;/code&gt; can't mock &lt;code&gt;retain&lt;/code&gt; or &lt;code&gt;release&lt;/code&gt;. This is why manual checks on the &lt;code&gt;retainCount&lt;/code&gt; are used instead of asking the mock object to expect a &lt;code&gt;retain&lt;/code&gt;. If you expect &lt;code&gt;autorelease&lt;/code&gt; to be used instead of &lt;code&gt;release&lt;/code&gt;, you'd need to wrap the tested method invocation in an &lt;code&gt;NSAutoreleasePool&lt;/code&gt; to flush the &lt;code&gt;autorelease&lt;/code&gt; before testing the &lt;code&gt;retainCount&lt;/code&gt;.&lt;/blockquote&gt;

&lt;p&gt;A final point about this test: it uses &lt;code&gt;object_getInstanceVariable&lt;/code&gt; and &lt;code&gt;object_setInstanceVariable&lt;/code&gt; to get the &lt;code&gt;windowController&lt;/code&gt; from the &lt;code&gt;appDelegate&lt;/code&gt; instead of the property accessor. The reason for this is that &lt;code&gt;object_getInstanceVariable&lt;/code&gt; directly reads the value from the object without invoking any accessor methods that might have secondary effects. Some code presented elsewhere uses &lt;code&gt;valueForKey:&lt;/code&gt; to achieve the same effect but the problem with this is that &lt;code&gt;valueForKey:&lt;/code&gt; will use the &lt;code&gt;window&lt;/code&gt; getter method if it exists &amp;mdash; we want to directly test that the actual instance variable is set on the class without interference.&lt;/p&gt;

&lt;h5&gt;applicationWillTerminate:&lt;/h5&gt;

&lt;p&gt;The final tests for the &lt;code&gt;WhereIsMyMacAppDelegate&lt;/code&gt; are for the &lt;code&gt;applicationWillTerminate:&lt;/code&gt; method. This method should close window and release it.&lt;/p&gt;

&lt;pre&gt;- (void)testApplicationWillTerminate
{
    WhereIsMyMacAppDelegate *appDelegate =
        [[[WhereIsMyMacAppDelegate alloc] init] autorelease];
    
    id mockWindowController = [OCMockObject mockForClass:[WhereIsMyMacWindowController class]];
    [mockWindowController retain];
    object_setInstanceVariable(appDelegate, "windowController", mockWindowController);
    
    NSUInteger preRetainCount = [mockWindowController retainCount];
    [[mockWindowController expect] close];

    [appDelegate applicationWillTerminate:nil];
    
    [mockWindowController verify];

    NSUInteger postRetainCount = [mockWindowController retainCount];
    STAssertEquals(postRetainCount, preRetainCount, @"Window controller not released");

    id windowController;
    object_getInstanceVariable(appDelegate, "windowController", (void **)&amp;windowController);
    STAssertNil(windowController, @"Window controller property not set to nil");
}&lt;/pre&gt;

&lt;p&gt;After creating an &lt;code&gt;appDelegate&lt;/code&gt; to test, this method creates a mock &lt;code&gt;WhereIsMyMacWindowController&lt;/code&gt;, tells it to expect a &lt;code&gt;close&lt;/code&gt; invocation, sets it as the &lt;code&gt;windowController&lt;/code&gt; on the &lt;code&gt;appDelegate&lt;/code&gt; to this new mock object, invokes &lt;code&gt;applicationWillTerminate:&lt;/code&gt; on the &lt;code&gt;appDelegate&lt;/code&gt;, verifies that the &lt;code&gt;close&lt;/code&gt; method was invoked, ensures that the &lt;code&gt;retainCount&lt;/code&gt; is decremented by one and that the &lt;code&gt;windowController&lt;/code&gt; instance variable is set to &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's three failing tests. One is more of an integration test than a unit test (since it relies on the &lt;code&gt;NSApplcation&lt;/code&gt; operating in place) but the others are genuine isolated unit tests on the &lt;code&gt;WhereIsMyMacAppDelegate&lt;/code&gt;. The implementation to pass these tests is less interesting but you can have a look at the sample project to see how I added code to pass these tests.&lt;/p&gt;

&lt;h4&gt;Window Controller Tests&lt;/h4&gt;

&lt;h5&gt;loadWindow integration&lt;/h5&gt;

&lt;p&gt;As with the application delegate, the first test is an integration test. We need to test that the &lt;code&gt;loadWindow&lt;/code&gt; method will load the required user interface elements from files in the bundle. This is similar to &lt;a href="http://chanson.livejournal.com/148204.html"&gt;Chris Hanson's "Trust by verify" approach&lt;/a&gt; except that I test the loading of the window separately from the &lt;code&gt;windowDidLoad&lt;/code&gt; and &lt;code&gt;window&lt;/code&gt; methods.&lt;/p&gt;

&lt;pre&gt;- (void)testLoadWindow
{
    [windowController loadWindow];

    WebView *webView;
    object_getInstanceVariable(windowController, "webView", (void **)&amp;webView);
    CLLocationManager *locationManager;
    object_getInstanceVariable(windowController, "locationManager", (void **)&amp;locationManager);
    NSTextField *locationLabel;
    object_getInstanceVariable(windowController, "locationLabel", (void **)&amp;locationLabel);
    NSTextField *accuracyLabel;
    object_getInstanceVariable(windowController, "accuracyLabel", (void **)&amp;accuracyLabel);
    NSButton *openInBrowserButton;
    object_getInstanceVariable(windowController, "openInBrowserButton", (void **)&amp;openInBrowserButton);
    
    STAssertTrue([windowController isWindowLoaded], @"Window failed to load");
    STAssertNotNil(webView, @"webView ivar not set on load");
    STAssertNotNil(locationLabel, @"locationLabel ivar not set on load");
    STAssertNotNil(accuracyLabel, @"accuracyLabel ivar not set on load");
    STAssertNotNil(openInBrowserButton, @"openInBrowserButton ivar not set on load");
    STAssertEqualObjects(windowController, [openInBrowserButton target],
        @"openInBrowserButton button doesn't target window controller");
    STAssertTrue([openInBrowserButton action] == @selector(openInDefaultBrowser:),
        @"openInBrowserButton button doesn't invoke openInDefaultBrowser:");
}&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;windowController&lt;/code&gt; is a fixture that's allocated in the &lt;code&gt;setUp&lt;/code&gt; method. The majority of this method then gets the instance variables from the &lt;code&gt;windowController&lt;/code&gt; after the &lt;code&gt;loadWindow&lt;/code&gt; method is invoked and tests that the required properties are all set.&lt;/p&gt;

&lt;p&gt;We can now test the &lt;code&gt;windowDidLoad&lt;/code&gt; method as a separate step to the &lt;code&gt;loadWindow&lt;/code&gt;. The &lt;code&gt;windowDidLoad&lt;/code&gt; should create a &lt;code&gt;CLLocationManager&lt;/code&gt; object, set the window controller as the &lt;code&gt;delegate&lt;/code&gt; and start location updates.&lt;/p&gt;

&lt;h5&gt;windowDidLoad&lt;/h5&gt;

&lt;pre&gt;- (void)testWindowDidLoad
{
    mockLocationManager = [OCMockObject mockForClass:[CLLocationManager class]];
    [[mockLocationManager expect] setDelegate:windowController];
    [[mockLocationManager expect] startUpdatingLocation];

    [windowController windowDidLoad];

    [mockLocationManager verify];
    
    object_setInstanceVariable(windowController, "locationManager", nil);
    mockLocationManager = nil;
}&lt;/pre&gt;

&lt;p&gt;This uses the same category override approach that was used in the &lt;code&gt;testApplicationDidFinishLaunching&lt;/code&gt; method to swap in a mock &lt;code&gt;CLLocationManager&lt;/code&gt; and ensure that the appropriate methods are invoked.&lt;/p&gt;

&lt;h5&gt;locationManager:didUpdateToLocation:fromLocation:&lt;/h5&gt;

&lt;p&gt;Next step: verify that the correct Google Maps location is loaded in the &lt;code&gt;WebView&lt;/code&gt;'s &lt;code&gt;mainFrame&lt;/code&gt; when a given coordinate is passed to the &lt;code&gt;WhereIsMyMacWindowController&lt;/code&gt; implementation of the &lt;code&gt;-[CLLocationManagerDelegate locationManager:didUpdateToLocation:fromLocation:]&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;This test method is pretty big but the essence is that:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;The web view and its main frame are mocked.&lt;/li&gt;
&lt;li&gt;The main frame is told to expect specific a specific HTML string that's loaded from a pre-created file.&lt;/li&gt;
&lt;li&gt;The method is then passed the exact location that should trigger that HTML string.&lt;/li&gt;
&lt;li&gt;The mock web frame is then asked to verify that the expected HTML string was loaded.&lt;/li&gt;
&lt;li&gt;The window's labels are also tested to ensure they receive the correct values.&lt;/ul&gt;

&lt;pre&gt;- (void)testUpdateToLocation
{
    NSString *htmlString =
        [NSString 
            stringWithContentsOfFile:
                [[NSBundle bundleWithIdentifier:@"com.yourcompany.UnitTests"]
                    pathForResource:@"WebPageTestContent" ofType:@"html"]
            encoding:NSUTF8StringEncoding
            error:NULL];
    id mockWebView = [OCMockObject mockForClass:[WebView class]];
    id mockWebFrame = [OCMockObject mockForClass:[WebFrame class]];
    [[[mockWebView stub] andReturn:mockWebFrame] mainFrame];
    [[mockWebFrame expect]
        loadHTMLString:htmlString
        baseURL:nil];
    object_setInstanceVariable(windowController, "webView", mockWebView);

    NSTextField *locationLabel = [[[NSTextField alloc] init] autorelease];
    NSTextField *accuracyLabel = [[[NSTextField alloc] init] autorelease];
    object_setInstanceVariable(windowController, "locationLabel", locationLabel);
    object_setInstanceVariable(windowController, "accuracyLabel", accuracyLabel);

    CLLocationCoordinate2D coord;
    coord.longitude = 144.96326388;
    coord.latitude = -37.80996889;
    CLLocation *location =
        [[[CLLocation alloc]
            initWithCoordinate:coord
            altitude:0
            horizontalAccuracy:kCLLocationAccuracyBest
            verticalAccuracy:kCLLocationAccuracyHundredMeters
            timestamp:[NSDate date]]
        autorelease];
    
    [windowController
        locationManager:nil
        didUpdateToLocation:location
        fromLocation:nil];
    [windowController
        locationManager:nil
        didUpdateToLocation:location
        fromLocation:location];
    
    [mockWebFrame verify];
    
    STAssertEqualObjects(
        ([locationLabel stringValue]),
        ([NSString stringWithFormat:@"%f, %f", coord.latitude, coord.longitude]),
        @"Location label not set.");
    STAssertEqualObjects(
        ([accuracyLabel stringValue]),
        ([NSString stringWithFormat:@"%f", kCLLocationAccuracyBest]),
        @"Location label not set.");
}&lt;/pre&gt;

&lt;p&gt;An interesting point to notice here is that the &lt;code&gt;WebPageTestContent&lt;/code&gt; file is loaded from a bundle that isn't the &lt;code&gt;mainBundle&lt;/code&gt;. This is because the test resides in the &lt;code&gt;UnitTests.octest&lt;/code&gt; bundle, not the application's bundle (which is the "main" bundle).&lt;/p&gt;

&lt;h5&gt;locationManager:didFailWithError: and openInDefaultBrowser:&lt;/h5&gt;

&lt;p&gt;I'll leave out the code for the &lt;code&gt;locationManager:didFailWithError:&lt;/code&gt; test &amp;mdash; it's largely the same as the previous test but with a different HTML string to load in the web view's main frame. You can see it in the downloaded project if you wish.&lt;/p&gt;

&lt;p&gt;Similarly, &lt;code&gt;openInDefaultBrowser:&lt;/code&gt; is just a URL, generated from the current location and sent to the shared &lt;code&gt;NSWorkspace&lt;/code&gt; (which we mock through category overrides) so the test contains largely the same elements &amp;mdash; so I'll omit the code for this test too. Again, check the downloaded project if you're interested.&lt;/p&gt;

&lt;h5&gt;dealloc:&lt;/h5&gt;

&lt;p&gt;All that remains is to create tests for the &lt;code&gt;dealloc&lt;/code&gt; method to ensure that the &lt;code&gt;locationManager&lt;/code&gt; receives a &lt;code&gt;stopUpdatingLocation&lt;/code&gt; and a &lt;code&gt;release&lt;/code&gt; message.&lt;/p&gt;

&lt;pre&gt;- (void)testDealloc
{
    id mockLocationManager = [OCMockObject mockForClass:[CLLocationManager class]];
    NSUInteger preRetainCount = [mockLocationManager retainCount];
    [mockLocationManager retain];
    object_setInstanceVariable(windowController, "locationManager", mockLocationManager);
    
    [[mockLocationManager expect] stopUpdatingLocation];

    [windowController dealloc];
    
    [mockLocationManager verify];

    NSUInteger postRetainCount = [mockLocationManager retainCount];
    STAssertEquals(postRetainCount, preRetainCount, @"Location manager not released");
    
    windowController = nil;
}&lt;/pre&gt;

&lt;p&gt;Notice that we have to set &lt;code&gt;windowController&lt;/code&gt; to &lt;code&gt;nil&lt;/code&gt; at the end. This is because invoking &lt;code&gt;dealloc&lt;/code&gt; on the &lt;code&gt;windowController&lt;/code&gt; fixture has deallocated it and we need to ensure that the &lt;code&gt;tearDown&lt;/code&gt; method doesn't try to invoke &lt;code&gt;release&lt;/code&gt; on it.&lt;/p&gt;

&lt;p&gt;Six failing tests for the &lt;code&gt;WhereIsMyMacWindowController&lt;/code&gt;. You can look at the downloadable project to see the code added to pass these tests.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;Download the complete &lt;a href="http://projectswithlove.com/projects/WhereIsMyMac-WithUnitTests.zip"&gt;WhereIsMyMac-WithUnitTests.zip&lt;/a&gt; (139kb).&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Custom executables (like the &lt;em&gt;UnitTestWhereIsMyMac&lt;/em&gt; discussed in this post) are part of user data in the project file, so you will not see the &lt;code&gt;UnitTestWhereIsMyMac&lt;/code&gt; custom executable in the downloaded project unless you create it yourself or your username happens to be "matt".&lt;br/&gt;&lt;br/&gt;This project includes &lt;a href="http://www.mulle-kybernetik.com/software/OCMock/"&gt;OCMock.framework&lt;/a&gt;, which is Copyright (c) 2004-2009 by Mulle Kybernetik. OCMock is covered by its own license (contained in the &lt;em&gt;OCMock.framework/Versions/A/Resources/License.txt&lt;/em&gt; file).&lt;/blockquote&gt;

&lt;p&gt;In this post, I created a Mac project, created unit tests for all required functionality (plus two integration tests) and ultimately added code to make the project pass those tests. I've shown the configuration required for unit testing targets in Xcode and the implementation of the tests themselves, which show how to isolate units of a program (using mock objects and category overrides) for properly decoupled unit testing.&lt;/p&gt;

&lt;p&gt;Unit tests for all created code does not mean that the project is "fully tested". There are lots of aspects associated with integration, runtime and memory behaviors, user events and the behaviors of the Cocoa frameworks that are not covered by these tests. Of course, this is the limit of "unit testing" for classes that operate in an application framework &amp;mdash; to test these other aspects requires different kinds of tests.&lt;/p&gt;

&lt;p&gt;Next week, I'll be presenting the same post developed for the iPhone. I apologize that this will result in two posts that almost the same but there are enough differences between the two that I couldn't squeeze both into a reasonable sized post. I also hope that by separating the posts, the result will be easier for dedicated Mac or iPhone programmers to follow.&lt;/p&gt;

&lt;p&gt;Finally, a disclaimer: please don't consider the existence of this post as a recommendation that you should necessarily write your applications with full unit tests. It is important to look at the work involved and weigh the associated time costs and against your project's need for unit level validation. There are alternative approaches for maintaining code quality that have different associated costs and benefits which I hope to discuss and compare in a later post.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-1348926749963474151?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/gD5t49YgiPg" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1348926749963474151?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1348926749963474151?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/gD5t49YgiPg/sample-mac-application-with-complete.html" title="A sample Mac application with complete unit tests" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cMQHkzeCp7ImA9WxBSE0o.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-8720063513230905648</id><published>2009-12-12T15:21:00.001-08:00</published><updated>2009-12-20T21:58:01.780-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-20T21:58:01.780-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Xcode" /><title>Multiple copy buffers, cursor and tab key tricks in Xcode</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;This week, I'll show you a few keyboard related tricks for editing in Xcode, including setting up multiple copy-and-paste buffers by adjusting the key mappings, switching tabs on or off for autocomplete and other text editing quirks in Xcode like understanding why the "End" key doesn't move to the end of the line on the Mac.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Key bindings, the cursor and Emacs&lt;/h4&gt;

&lt;p&gt;Standard text editing on the Mac obeys many more keyboard commands than most casual users realize. This is because the key bindings on the Mac derive from NeXTStep which chose to implement (where possible) a large number of the Emacs key bindings.&lt;/p&gt;

&lt;p&gt;First developed in the 1970's, Emacs was designed for keyboards that lacked cursor and forward delete keys and computers that lacked a mouse. And, like its spiritual enemy in the world of text editing, Vi, Emacs was never a program to update its key bindings to stay current.&lt;/p&gt;

&lt;p&gt;What this means is that text editing applications that use the standard Cocoa text editor &amp;mdash; like TextEdit.app &amp;mdash; and other more sophisticated text editors that support the operating system's default key bindings &amp;mdash; like Xcode &amp;mdash; support most of the Emacs key controls for navigating and editing &amp;mdash; like Ctrl-F and Ctrl-B for forward and backward by one character or Ctrl-A and Ctrl-E for jump to the start or end of the paragraph.&lt;/p&gt;

&lt;p&gt;Of course, most of this is pointless to ordinary users since the standard cursor and home keys will do this in a far less cryptic way.&lt;/p&gt;

&lt;p&gt;For those of you who still scream at Xcode when the Home key doesn't move to the start of the line or get annoyed that the cursor doesn't move when using PageUp/PageDown, here's a quick refresher:&lt;/p&gt;

&lt;table style="margin-left:10%;width:80%;"&gt;
&lt;thead&gt;&lt;tr&gt;&lt;td&gt;Key&amp;nbsp;or&amp;nbsp;combination&lt;/td&gt;&lt;td&gt;Action&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;
&amp;uarr;&lt;/td&gt;&lt;td&gt;cursor up&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&amp;darr;&lt;/td&gt;&lt;td&gt;cursor down&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&amp;larr;&lt;/td&gt;&lt;td&gt;cursor left&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&amp;rarr;&lt;/td&gt;&lt;td&gt;cursor right&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Command &amp;larr;&lt;/td&gt;&lt;td&gt;cursor to start of line&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Command &amp;rarr;&lt;/td&gt;&lt;td&gt;cursor to end of line&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Option &amp;larr;&lt;/td&gt;&lt;td&gt;cursor to start of previous word&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Option &amp;rarr;&lt;/td&gt;&lt;td&gt;cursor to end of previous word&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Control &amp;larr;&lt;/td&gt;&lt;td&gt;cursor to start of previous camel-case component (Xcode only &amp;mdash; otherwise it works like Command &amp;larr;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Control &amp;rarr;&lt;/td&gt;&lt;td&gt;cursor to end of previous camel-case component (Xcode only &amp;mdash; otherwise it works like Command &amp;rarr;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
PageUp or Control &amp;uarr;&lt;/td&gt;&lt;td&gt;scroll up one page, without moving the cursor&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
PageDown&amp;nbsp;or&amp;nbsp;Control&amp;nbsp;&amp;darr;&lt;/td&gt;&lt;td&gt;scroll down one page, without moving the cursor&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Home&lt;/td&gt;&lt;td&gt;scroll to top of document, without moving the cursor&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
End&lt;/td&gt;&lt;td&gt;scroll to end of document, without moving the cursor&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Option-PageUp&lt;/td&gt;&lt;td&gt;scroll up one page, moving cursor to center of new location&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Option-PageDown&lt;/td&gt;&lt;td&gt;scroll down one page, moving cursor to center of new location&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Command &amp;uarr;&lt;/td&gt;&lt;td&gt;move cursor to start of document&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Command &amp;darr;&lt;/td&gt;&lt;td&gt;move cursor to end of document&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Option &amp;uarr;&lt;/td&gt;&lt;td&gt;move cursor to start of the paragraph (except in Xcode where it does nothing)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
Option &amp;darr;&lt;/td&gt;&lt;td&gt;move cursor to end of the paragraph (except in Xcode where it does nothing)&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p align="center"&gt;&lt;em&gt;Due to the importance of the Home/End/PageUp/PageDown keys in text editing, I have no respect for Apple's choice to start shipping keyboards without these keys by default on new computers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I wish there was a little more sense to these bindings. There almost are a few rules &amp;mdash; like Control, Option and Command represent small, medium and largest increments in any direction and combinations involving the cursor keys move the cursor but Home/End/PageUp/PageDown combinations just scroll without moving the cursor &amp;mdash; but sadly there are enough violations of these rules that you must simple learn them all by rote.&lt;/p&gt;

&lt;p&gt;The ability to scroll the document without moving the cursor when desired on the Mac is an ability that I sorely miss when I'm stuck using Visual Studio or other development environments &amp;mdash; in these other environment, my cursor always gets stranded when I quickly glance at another point in the document, whereas on the Mac I can just tap a left or right arrow to return to where I was.&lt;/p&gt;

&lt;h4&gt;Kill and yank&lt;/h4&gt;

&lt;p&gt;A side effect of bringing Emacs key bindings into Xcode though is that a few Emacs commands that don't have common Macintosh equivalents are brought in as well.&lt;/p&gt;

&lt;p&gt;This includes kill and yank. Kill and yank are Ctrl-K and Ctrl-Y by default.&lt;/p&gt;

&lt;p&gt;In most respects, kill and yank work like cut and paste. Kill something and it gets stored in your kill buffer, yank and the contents of your kill buffer are inserted at the current insertion point. If you have no selection, kill will delete from the cursor to the end of the line, otherwise it will only delete the selection. There are a few differences compared to cut-and-paste: you can't yank between applications (each application has its own, non-shared kill ring) and they store pure text only (no styled text, images or other copyable data).&lt;/p&gt;

&lt;p&gt;In their default setup, kill and yank are like a second-rate extra cut-and-paste option. But correctly configured, you can have as many separate cut buffers as you want.&lt;/p&gt;

&lt;h5&gt;Setting up kill-and-yank&lt;/h5&gt;

&lt;p&gt;The first configuration change you need to make is to set up a binding for &lt;code&gt;yankAndSelect:&lt;/code&gt; instead of ordinary &lt;code&gt;yank:&lt;/code&gt;. We do this because &lt;code&gt;yank:&lt;/code&gt; will only ever insert the most recently killed text whereas &lt;code&gt;yankAndSelect:&lt;/code&gt; allows you to cycle through all stored buffers. You can do this in the "Xcode Preferences&amp;rarr;Key Bindings&amp;rarr;Text Key Bindings" but I prefer to make the binding System-wide by using the "&lt;code&gt;/Developer/Applications/Utilities/Property List Editor.app&lt;/code&gt;" to create a file at "&lt;code&gt;~/Library/KeyBindings/DefaultKeyBinding.dict&lt;/code&gt;" that overrides the &lt;code&gt;yank:&lt;/code&gt; command with a &lt;code&gt;yankAndSelect:&lt;/code&gt; command.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/SyNM0MfpXbI/AAAAAAAAAik/EVXuTpa_X5U/yankAndSelectBinding.png?imgmax=800" alt="yankAndSelectBinding.png" border="0" width="532" height="156" /&gt;

&lt;p align="center"&gt;&lt;em&gt;The key string is actually caret-y, not Ctrl-Y. You may need to create the KeyBindings&lt;br/&gt;directory in your Library directory as it is not there by default.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Both &lt;code&gt;yank:&lt;/code&gt; and &lt;code&gt;yankAndSelect:&lt;/code&gt; are standard commands on &lt;code&gt;NSReponder&lt;/code&gt;, so this just exchanges one for another. In a totally bizarre twist of documentation, &lt;code&gt;yankAndSelect:&lt;/code&gt; is an undocumented method (it's not in the Cocoa.h headers) that &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/EventOverview/TextDefaultsBindings/TextDefaultsBindings.html"&gt;appears in the documentation where you are encouraged to used it as required&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The other step to make multiple kill buffers work is to specify how many buffers you want. By default, there is 1 but we want multiple buffers.&lt;/p&gt;

&lt;p&gt;To do this, just add the key &lt;code&gt;NSTextKillRingSize&lt;/code&gt; with a string or number value greater than 1 to any .plist file. For example, if you only want this behavior added to Xcode, add the line to the Xcode .plist file.&lt;/p&gt;

&lt;p&gt;I like to add this like to my Global Preferences. To do this, type:&lt;/p&gt;

&lt;pre&gt;open ~/Library/Preferences/.GlobalPreferences.plist&lt;/pre&gt;

&lt;p&gt;in a Terminal window (the file is hidden by default in the Finder so you need to open it like this unless you've turned the display of hidden files on).&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SyNPDDg3wHI/AAAAAAAAAis/6PmiTn_t-Ow/killbuffers.png?imgmax=800" alt="killbuffers.png" border="0" width="424" height="60" /&gt;

&lt;p align="center"&gt;&lt;em&gt;The &lt;code&gt;NSTextKillRingSize&lt;/code&gt; setting in my .GlobalPreferences.plist file.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With these changes, you can use Control-K to copy something to a kill buffer and then Control-Y to cycle through the last 3 items stored in your kill buffers (the collection of kill buffers is called the "kill ring"). You can use any number or kill buffers but large numbers may make cycling through the complete set harder (since you can only cycle through in one direction).&lt;/p&gt;

&lt;h4&gt;The Tab key binding in Xcode&lt;/h4&gt;

&lt;p&gt;While I'm talking about key bindings, one of the biggest shocks in Xcode 3.2 for me was the fact that the Tab key is configured by default to select the next Code Sense Completion, instead of inserting a Tab character.&lt;/p&gt;

&lt;p&gt;This meant that if I had code like this:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SyNRg65olBI/AAAAAAAAAi4/kJl5tzEgGO0/autocomplete.png?imgmax=800" alt="autocomplete.png" border="0" width="550" height="58" /&gt;

&lt;p&gt;and I hit the Tab key to indent the second line, it wouldn't indent &amp;mdash; instead the autocomplete field would be selected.&lt;/p&gt;

&lt;p&gt;I found this particularly frustrating since I normally use Ctrl-/ to select autocomplete fields, making the Tab key redundant as well as interfering.&lt;/p&gt;

&lt;p&gt;Fortunately, Xcode supports a "Insert Tab without Extra Action" that is normally bound to Option-Tab which will only ever insert a Tab character (will never perform other UI actions). By exchanging the key bindings between "Insert Tab" and "Insert Tab without Extra Action", my complaint was solved.&lt;/p&gt;

&lt;blockquote style="width:50%;float:right;font-size:12px;margin-left:10px;"&gt;&lt;strong&gt;On the topic of search and replace:&lt;/strong&gt; a change to menus in Xcode 3.2 means that single file Search and Replace no longer appears in the menu (unless you're holding down the Control key, since its binding is now Ctrl-Command-F and "Ctrl" variants of menu items aren't shown unless "Ctrl" is held). This can make search and replace hard to find in Xcode 3.2. Another feature that has become harder to find are the search options &amp;mdash; the little magnifying glass on the search field hides a popup menu that contains the essential options like "Ignore case".&lt;/blockquote&gt;

&lt;p&gt;A sideeffect of changing the tab bindings is that all text fields in the user interface &amp;mdash; including the Search and Replace text fields &amp;mdash; will change their behavior when the Tab key is pressed. Once the bindings are changed, Tab will no longer move the input focus from the search field to the replace field &amp;mdash; it will instead insert the tab character into the selected field. This means that to jump from the Search field to the Replace field you will need to type Option-Tab. Of course, the ability to easily enter tab characters in the search field has its advantages too.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Text editing on the Mac is loaded with features that most people never use. While there's often no need to use many of the extra features, extra navigation options or extra kill-and-yank buffers can be useful additions.&lt;/p&gt;

&lt;p&gt;The .GlobalPreferences.plist and global DefaultKeyBinding.dict files used to alter global key mappings provide a surprising amount of flexibility to applications that respect their content, like Xcode. You can use them to remap most key combinations to other commands if you choose. A corollary though: you should try to respect these dictionaries if writing your own custom text editor.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-8720063513230905648?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/MAqfahxM5Cg" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8720063513230905648?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8720063513230905648?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/MAqfahxM5Cg/multiple-copy-buffers-cursor-and-tab.html" title="Multiple copy buffers, cursor and tab key tricks in Xcode" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/12/multiple-copy-buffers-cursor-and-tab.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUANQHYyfyp7ImA9WxBTE04.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-1577607452936425830</id><published>2009-12-08T03:17:00.001-08:00</published><updated>2009-12-08T21:49:51.897-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-08T21:49:51.897-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cocoa Touch" /><category scheme="http://www.blogger.com/atom/ns#" term="UIKit" /><category scheme="http://www.blogger.com/atom/ns#" term="object-oriented design" /><title>The design of an iPhone application</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In this post, I'll discuss iPhone program design using the example of a small but non-trivial iPhone application to provide examples of how the design is implemented. The design includes: how to manage data coming from different sources, how to manage multiple views of that data and how to design your program so it remains simple and manageable as it grows. In short, I'll be discussing how Model-View-Controller (MVC) applies to an iPhone application but I'll also discuss how even simple programs are considerably more hierarchic through their controllers and branched through their models and views than the basic description "Model-View-Controller" might imply.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;The sample program&lt;/h4&gt;

&lt;p&gt;The sample program for this post takes the Core Data SQL database of Australian Postcodes that I &lt;a href="http://cocoawithlove.com/2009/11/writing-parser-using-nsscanner-csv.html"&gt;created last week from a CSV file&lt;/a&gt; and uses that in an iPhone application that allows you to:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Browse and search the database.&lt;/li&gt;
&lt;li&gt;Display entries in a &lt;code&gt;MKMapView&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Find the nearest entry to the user's GPS and display that on a map.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The following screenshots show the basic flow of the application.&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/Sx3TvosGQ8I/AAAAAAAAAg0/bityb5keyZE/IMG_0018.PNG?imgmax=800" alt="IMG_0018.PNG" border="0" width="180" height="270" style="display:inline;"/&gt;
&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/Sx3TzNEkLrI/AAAAAAAAAhA/em9-MuI0PY4/IMG_0020.PNG?imgmax=800" alt="IMG_0020.PNG" border="0" width="180" height="270" style="display:inline;"/&gt;
&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Sx3T29wGdBI/AAAAAAAAAhM/Ow4jeAg_rdI/IMG_0021.PNG?imgmax=800" alt="IMG_0021.PNG" border="0" width="180" height="270" style="display:inline;"/&gt;

&lt;p&gt;The "Show current location" step skips the middle screenshot in the workflow and goes straight to the map, displaying the closest "Postcode" in the database for the user's location, or just the user's location (with no pins in the map) if they are more than 0.1 longitude or latitude away from the nearest post office.&lt;/p&gt;

&lt;blockquote&gt;You can download the complete project &lt;a href="http://projectswithlove.com/projects/AustralianPostcodes.zip"&gt;AustralianPostcodes.zip&lt;/a&gt; (961kB).&lt;/blockquote&gt;

&lt;h4&gt;Steps in designing a program&lt;/h4&gt;

&lt;p&gt;The basic steps in designing a small user program are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Decide what the program will display to the user.&lt;/li&gt;
&lt;li&gt;Work out how the user will navigate through the program to reach each view.&lt;/li&gt;
&lt;li&gt;Work out the data that is needed to populate the views that the user will navigate.&lt;/li&gt;
&lt;li&gt;Decide where that data will come from and how you will manage access to it.&lt;/li&gt;
&lt;li&gt;Decide how and when you will construct your views.&lt;/li&gt;
&lt;li&gt;Decide how you will provide your views with data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first two points are the program's requirements and the remainder is the high level design. For this post, I'm 
going to consider the first two points complete (as given in the previous section).&lt;/p&gt;

&lt;p&gt;I'll discuss steps 3 and 4 as a single concept "Program data", then steps 5 and 6 as "Program construction".&lt;/p&gt;

&lt;h4&gt;Program data&lt;/h4&gt;

&lt;p&gt;While it might not be obvious, this program actually has 3 different sources of data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Postcodes and their related data&lt;/li&gt;
&lt;li&gt;The GPS location&lt;/li&gt;
&lt;li&gt;The cache of fetched postcodes, filtered by search terms&lt;/li&gt;
&lt;li&gt;The cache of postcodes nearest the selected location or GPS location&lt;/li&gt;
&lt;li&gt;List of menu items on the top-level page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last item doesn't need to be data (it could easily be done in code) but I wanted to talk about a range of different data sources and implementing menus like this from data can dramatically reduce the size and complexity of your code (see my earlier post &lt;a href="http://cocoawithlove.com/2008/11/simplifying-your-code-using.html"&gt;Simplifying your code using NSDictionary&lt;/a&gt;).&lt;/p&gt;

&lt;h5&gt;Postcode data and the PostcodeController&lt;/h5&gt;

&lt;p&gt;Obviously in this program, the Core Data SQL database is the source of the postcode data. However, there is more to clarifying the data source than that.&lt;/p&gt;

&lt;p&gt;The postcode data is used from multiple views in the application. For this reason, it will need to live in its own persistent location that views can access when needed. To handle its creation, persistence and access, we'll need some form of controller to manage the lifecycle of this data and access to it.&lt;/p&gt; 

&lt;p&gt;Core Data runs in an &lt;code&gt;NSManagedObjectContext&lt;/code&gt;. In some respects, you may consider that the &lt;code&gt;NSManagedObjectContext&lt;/code&gt; manages access to the data. While this is true at the low level of reading, writing, cacheing and fetching, the reality is that &lt;code&gt;NSManagedObjectContext&lt;/code&gt; is not a manager in a broader sense for your program and your program specific logic.&lt;/p&gt;

&lt;p&gt;Specifically, your program will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A way to construct the Core Data persistence stack (i.e. open a Core Data SQL store and create an &lt;code&gt;NSManagedObjectContext&lt;/code&gt; for it).&lt;/li&gt;
&lt;li&gt;A way to access the current context from anywhere in the program.&lt;/li&gt;
&lt;li&gt;A place to put context processing code (if needed). This might include importing/exporting code, specialized fetching code, editing and validating code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While this iPhone application doesn't need the last point, the first two are necessary.&lt;/p&gt;

&lt;p&gt;In the default Xcode template for an iPhone application using Core Data, the &lt;code&gt;NSManagedObjectContext&lt;/code&gt; is constructed in the &lt;code&gt;AppDelegate&lt;/code&gt; object and from there is pushed onto the &lt;code&gt;RootViewController&lt;/code&gt; so that it can be used there.&lt;/p&gt;

&lt;p&gt;Simply put: I dislike this approach because it gives the &lt;code&gt;AppDelegate&lt;/code&gt; multiple responsibilities unrelated to its primary purpose.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;AppDelegate&lt;/code&gt; exists to implement functionality during key points in the &lt;code&gt;UIApplication&lt;/code&gt;'s lifecycle (most importantly startup and shutdown). The &lt;code&gt;AppDelegate&lt;/code&gt; doesn't use the &lt;code&gt;NSManagedObjectContext&lt;/code&gt; for itself and the &lt;code&gt;AppDelegate&lt;/code&gt;'s primary responsibility is not document management &amp;mdash; you should not be using your &lt;code&gt;AppDelegate&lt;/code&gt; as your application's document manager.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Every class should have a single purpose&lt;/strong&gt;&lt;br/&gt;Every piece of functionality that a class exposes to the rest of the program (i.e. functionality that is part of the class' external interface) should be obviously part of that class' primary role in the program.&lt;/blockquote&gt;

&lt;p&gt;For this reason, I create a class (in this project it is named &lt;code&gt;PostcodesController&lt;/code&gt;) whose responsibility it is to construct the document (our &lt;code&gt;NSManagedObjectContext&lt;/code&gt;) and handle access to it or process the document if needed.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;PostcodesController&lt;/code&gt; will be a singleton, as most document managers are (see the &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ApplicationKit/Classes/NSDocumentController_Class/Reference/Reference.html"&gt;&lt;code&gt;NSDocumentController&lt;/code&gt; in Mac OS X&lt;/a&gt;). Since the application only has one set of Postcode data, there is no need to select the "current" document or manage a set of Core Data persistence stacks but this class is where that behavior would be added if needed in future.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;PostcodesController&lt;/code&gt; is then acccessed by the &lt;code&gt;PostcodesViewController&lt;/code&gt; to get the current context. However, the data this context contains is not used directly; it is cached by the &lt;code&gt;NSFetchedResultsController&lt;/code&gt; as a separate set of data and from there it is used to populate the table view.&lt;/p&gt;

&lt;h5&gt;Map data&lt;/h5&gt;

&lt;p&gt;Map data in the application consists of three parts:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;The map "tiles" (the street map shown in the view)&lt;/li&gt;
&lt;li&gt;The "current location" (which is either the result of a selection or the GPS location).&lt;/li&gt;
&lt;li&gt;The array of pins displayed in the map&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The actual map tiles are loaded by the &lt;code&gt;MKMapView&lt;/code&gt; that Apple's MapKit provides. We don't really need to worry about that.&lt;/p&gt;

&lt;p&gt;The selected location or GPS location is a little trickier. This either comes from the user's selection on a previous screen or from the &lt;code&gt;CLLocationManager&lt;/code&gt; (which supplies us with location data from the GPS). If this was used by multiple views in the application, then we would need a special class to manage the current location for the whole application (like the &lt;code&gt;PostcodeController&lt;/code&gt; manages the postcode database for the whole application) however, we only need location data on the map screen, so the &lt;code&gt;MapViewController&lt;/code&gt; which manages this screen can handle this.&lt;/p&gt;

&lt;p&gt;The array of pins displayed on the map is really just a selection of the data from the postcodes database, selected using criteria from the current location. Again, since this is only used on the map screen, so it can be controlled by the &lt;code&gt;MapViewController&lt;/code&gt; as long as the difficulty of doing so remains low.&lt;/p&gt;

&lt;h5&gt;List of menu items&lt;/h5&gt;

&lt;p&gt;Sometimes, data is so simple to load and so customized to the location where it will be used that managing it is no concern at all. The array of dictionaries that provides the structure for the "Main Menu" in the program is a good example of this &amp;mdash; the data can be read in a single instruction, its format is written to match the format that the "Main Menu" wants, it has no state to maintain and doesn't require any editing.&lt;/p&gt;

&lt;h4&gt;Program construction&lt;/h4&gt;

&lt;p&gt;This program started with a "Navigation-based application" template in Xcode and the project name "AustralianPostcodes". This means that the following steps are setup by the template:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;UIApplication&lt;/code&gt; will load the &lt;em&gt;MainWindow.xib&lt;/em&gt; on startup&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;MainWindow.xib&lt;/em&gt; will construct the &lt;code&gt;AustralianPostcodesAppDelegate&lt;/code&gt;, a &lt;code&gt;UIWindow&lt;/code&gt; and a &lt;code&gt;UINavigationController&lt;/code&gt; which will load the &lt;code&gt;RootViewController&lt;/code&gt; from &lt;em&gt;RootViewController.xib&lt;/em&gt; and set it as the top level view in the navigation hierarchy.&lt;/li&gt;
&lt;li&gt;The AustralianPostcoddesAppDelegate will insert the &lt;code&gt;UINavigationController&lt;/code&gt;'s view into the &lt;code&gt;UIWindow&lt;/code&gt; and display the window.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The primary controllers in the program are the &lt;code&gt;PostcodesController&lt;/code&gt; (which controls the construction of the Core Data persistence stack), the &lt;code&gt;RootViewController&lt;/code&gt; (which shows the main menu), the &lt;code&gt;PostcodesViewController&lt;/code&gt; (which displays the table of objects fetched from Core Data) and the &lt;code&gt;MapViewController&lt;/code&gt; (which displays a single &lt;code&gt;Postcode&lt;/code&gt; object and the map view).&lt;/p&gt;

&lt;h5&gt;Constructing the RootViewController&lt;/h5&gt;

&lt;p&gt;The &lt;code&gt;RootViewController&lt;/code&gt; needs to display its list of options in the table. When any row in the table is tapped, a new UIViewController subclass will need to be constructed and pushed onto the &lt;code&gt;UINavigationController&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Due to the data-configured nature of the &lt;code&gt;RootViewController&lt;/code&gt;, the subclass of &lt;code&gt;UIViewController&lt;/code&gt; constructed and any parameters passed into its initializer are all specified in the data file.&lt;/p&gt;

&lt;p&gt;This means that this class is incredibly simple. The three different rows perform three different tasks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load a PostcodesViewController and sort by postcode&lt;/li&gt;
&lt;li&gt;Load a PostcodesViewController and sort by suburb&lt;/li&gt;
&lt;li&gt;Load a MapViewController and use the GPS for location data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But the differences come from the data. The work done by the &lt;code&gt;RootViewController&lt;/code&gt; is the same in each case.&lt;/p&gt;

&lt;h5&gt;Constructing the PostcodesViewController&lt;/h5&gt;

&lt;p&gt;This class displays the postcode data but it has to perform four tasks as part of that job:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch the sorted (and possibly filtered) postcodes from the database&lt;/li&gt;
&lt;li&gt;Construct/configure the table view cells to display the fetched results in the table&lt;/li&gt;
&lt;li&gt;Respond to changes in the search string by refetching the data&lt;/li&gt;
&lt;li&gt;Respond to taps on a row by loading a MapViewController to display the map&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this case, much of the first step is handled by a standard &lt;code&gt;NSFetchResultsController&lt;/code&gt;. This class is designed to work closely with the &lt;code&gt;UITableView&lt;/code&gt; so it makes sense to keep this work close to the view. If we weren't using an approach so closely tied to the view, it would also be possible to put a fetch method in the &lt;code&gt;PostcodesController&lt;/code&gt; and pass parameters to it so that it prepared the data in an appropriate format.&lt;/p&gt;

&lt;p&gt;When a row is selected, the &lt;code&gt;Postcode&lt;/code&gt; object (the subclass of &lt;code&gt;NSManagedObject&lt;/code&gt; associated with the selected row) is passed into a newly constructed &lt;code&gt;MapViewController&lt;/code&gt;.&lt;/p&gt;

&lt;h5&gt;Constructing the MapViewController&lt;/h5&gt;

&lt;p&gt;The &lt;code&gt;MapViewController&lt;/code&gt; needs to perform the following tasks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If not given a selected Postcode object, then the Postcode in the database nearest the GPS location must be fetched.&lt;/li&gt;
&lt;li&gt;Postcodes around the current location must be fetched and displayed on the map&lt;/li&gt;
&lt;li&gt;The map view must be centered on the selected postcode&lt;/li&gt;
&lt;li&gt;Details about the selected postcode must be displayed in the &lt;code&gt;UILabel&lt;/code&gt;s at the top of the screen.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To enable the easy display of postcodes as points on the map, the &lt;code&gt;Postcode&lt;/code&gt; class (the subclass of &lt;code&gt;NSManagedObject&lt;/code&gt; used by the Postcode entity in the Core Data model) implements the &lt;code&gt;MKAnnotation&lt;/code&gt; protocol. This means that the &lt;code&gt;Postcode&lt;/code&gt; objects returned from a fetch can be immediately added to the &lt;code&gt;MKMapView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This class needs to perform its own fetching from the Core Data database. Since the &lt;code&gt;PostcodesViewController&lt;/code&gt; and &lt;code&gt;MapViewController&lt;/code&gt; both need to fetch (albeit in slightly different ways) and they both use a significant volume of code of to do this fetching, it is possible that a common interface to perform fetch actions for both would be a future improvement.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Always be ready to iteratively refactor&lt;/strong&gt;&lt;br/&gt;As you implement a program, you should always be on the lookout for easy ways to simplify your program by implementing minor redesigns. Looking for multiple places where your program repeats the same functionality is the most prominent example of this. A corollary to this is that you should never copy and paste blocks of code &amp;mdash; a copy and pasted block of code should be a single method/function/macro that you simply invoke from multiple places.&lt;/blockquote&gt;

&lt;h4&gt;Model-View-Controller&lt;/h4&gt;

&lt;p&gt;Interpreting this program according to model-view-controller would go like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Model&lt;/strong&gt; &amp;mdash; the &lt;code&gt;Postcode&lt;/code&gt; objects in the &lt;code&gt;NSManagedObjectContext&lt;/code&gt; are the model.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;View&lt;/strong&gt; &amp;mdash; the &lt;code&gt;UITableViewCell&lt;/code&gt; objects on the "Main Menu", "By suburb" and "By postcode" screens and the &lt;code&gt;MKMapView&lt;/code&gt; on the map screen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Controller&lt;/strong&gt; &amp;mdash; the &lt;code&gt;AustralianPostcodesAppDelegate&lt;/code&gt;, &lt;code&gt;RootViewController&lt;/code&gt;, &lt;code&gt;PostcodesViewController&lt;/code&gt;, &lt;code&gt;MapViewController&lt;/code&gt;, &lt;code&gt;PostcodesController&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Why do we need so many controllers?&lt;/h5&gt;

&lt;p&gt;An interesting point to note is that every class in the project (with the exception of &lt;code&gt;Postcode&lt;/code&gt;) is a controller class.&lt;/p&gt;

&lt;p&gt;Why do we need so many controllers? The answer is that we have a normal number of controllers &amp;mdash; the correct analysis is that we have is an absence of custom model and view objects.&lt;/p&gt;

&lt;p&gt;A well written model object or view object needs no custom code for customization &amp;mdash; the construction provided by the controller and the data (provided from configuration files on construction or from model objects when loaded) is all the customization that they require.&lt;/p&gt;

&lt;p&gt;I've written posts about &lt;a href="http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html"&gt;drawing customizing table views without subclassing any views&lt;/a&gt; &amp;mdash; the customization comes from how the view is constructed and set up.&lt;/p&gt;

&lt;p&gt;On the model side, &lt;code&gt;NSManagedObject&lt;/code&gt; is configured by the &lt;em&gt;.xcdatamodel&lt;/em&gt; file and can be used without further configuration if desired. Similarly, &lt;code&gt;NSDictionary&lt;/code&gt; is used by the &lt;code&gt;RootViewController&lt;/code&gt; to hold custom structure data without need for custom behavior.&lt;/p&gt;

&lt;p&gt;Obviously you will probably need custom model and view objects at some point but the fewer you have, the easier things will be.&lt;/p&gt;

&lt;h5&gt;A simple diagram of the program&lt;/h5&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Sx4RYa6BNnI/AAAAAAAAAh0/-QjzcJnNHmM/basicMVC.png?imgmax=800" alt="basicMVC.png" border="0" width="450" height="347" /&gt;

&lt;p&gt;Generally though, I don't like this type of over-simplification. My problem is that while it does describe a single Model-View-Controller path through the program, this program has multiple sources of data and each source of data is managed at a different point and displayed in a different way.&lt;/p&gt;

&lt;h4&gt;A different way to think about application design&lt;/h4&gt;

&lt;p&gt;Despite the simplistic diagram shown above, the reality is that we have the following model-controller relationships in the program:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Postcodes&lt;/code&gt; in the &lt;code&gt;NSManagedObjectContext&lt;/code&gt;, controlled by &lt;code&gt;PostcodesController&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;Plist&lt;/em&gt; which describes the &lt;em&gt;Main Menu&lt;/em&gt;, controlled by &lt;code&gt;RootViewController&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The cached fetch of &lt;code&gt;Postcodes&lt;/code&gt; by suburb or postcodes, controlled by &lt;code&gt;NSFetchedResultsController&lt;/code&gt; in conjunction with &lt;code&gt;PostcodesViewController&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The cached fetch of nearest &lt;code&gt;Postcodes&lt;/code&gt;, controlled by &lt;code&gt;MapViewController&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The GPS location, controlled by &lt;code&gt;CLLocationManager&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So a full diagram of the data paths through the program would be considerably more complex than the diagram shown above.&lt;/p&gt;

&lt;p&gt;An important point to note about the above diagram is that there are two layers of controllers: one layer that controls the model at the top and one layer that controls the views at the bottom. The result of this observation is that the view-and-controller pairs and the the model-and-controller pairs are really two instances of the same design pattern. This means that we can add the following view-controller relationships to the list of model-controller relationships shown above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;UITableViewCells&lt;/code&gt; in the &lt;code&gt;UITableView&lt;/code&gt;s, controlled by &lt;code&gt;PostcodesViewController&lt;/code&gt; and &lt;code&gt;RootViewController&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;UILabels&lt;/code&gt; and the &lt;code&gt;MKMapView&lt;/code&gt;, controlled by the &lt;code&gt;MapViewController&lt;/code&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Module-controller&lt;/h5&gt;

&lt;p&gt;What this does is to break the entire program down into pairings of:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Class that "does" something (store data, display data, fetch data)&lt;/li&gt;
&lt;li&gt;and Controller which loads and configures it&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Your program is then a hierarchy of controllers (UIApplication/AppDelegate, Document controller, UIViewController subclasses) which load and configure their own modules (.xib files and windows, Core Data, UIView classes) to perform their actual work &amp;mdash; but these modules have no connections to the rest of the program, they rely entirely on the controller to set them up, provide their data and make them work.&lt;/p&gt;

&lt;p&gt;As your program grows larger and more complex, your controllers may have sub-controllers &amp;mdash; in fact, your module objects may become controllers to their own sub-module objects. Through this structure, you can have a giant program but each element is still simple within itself. Simplicity remains as the program grows because every individual element is self-contained.&lt;/p&gt;

&lt;h5&gt;Implications of this way of thinking&lt;/h5&gt;

&lt;blockquote&gt;&lt;strong&gt;The best programs are highly modular and decoupled&lt;/strong&gt;&lt;br/&gt;
A good application has tightly focussed modules which are totally decoupled from the rest of the program and controllers which are lightly coupled to other controllers in a hierarchical arrangement through the program but do nothing other than provide the contextual information for their controlled objects.&lt;/blockquote&gt;

&lt;p&gt;The idea is to make all aspects of your program clean, decoupled and resusable, in the same way that good view and model classes are.&lt;/p&gt;

&lt;p&gt;I prefer this way of thinking about application design. In essence, treat every data object, every network connection and every view object in the program (any class which "does" something) in the same way: like its own independent module. These independent module classes should:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;have their own controller which loads and configures them&lt;/li&gt;
&lt;li&gt;not have a connection (pointer or reference) to any other part of the program (except other objects within the module)&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;If you feel like one of these module objects needs to access another part of the program, try to redesign so that the controller pushes the information to the modular class, instead of the module object fetching for itself.&lt;/p&gt;

&lt;p&gt;The corollary to this is that your controller objects should, as much as possible, avoid "doing" anything except constructing and configuring these document-like objects. Controllers may have a lot of code compared to the module classes but that code should always be responding to a change from a module object and passing a message to another module or constructing another module. Controllers are all about setup, reactions and inter-module communication.&lt;/p&gt;

&lt;p&gt;Most of the time, the module objects controlled by the controller will not be your own special subclasses &amp;mdash; often they're just default &lt;code&gt;NSDictionary&lt;/code&gt; objects or &lt;code&gt;UIViews&lt;/code&gt; or &lt;code&gt;NSManagedObjects&lt;/code&gt; &amp;mdash; but it is important to keep the module object and controller relationship in mind to help guide how you write your program.&lt;/p&gt;

&lt;h5&gt;Keep the main advantage of Model-View-Controller thinking&lt;/h5&gt;

&lt;p&gt;Even if you do start thinking about every component in your program in module-controller terms, you shouldn't drop the key advantage of Model-View-Controller &amp;mdash; to focus your application around the workflow of your "model".

&lt;p&gt;Specifically: you should always know what the "model" of your program is. All aspects of your program should be directed towards showing, editing, displaying that data. Even if lots of other modules, tasks and activities are implemented as part of the overall process, they should not disrupt the model's workflow.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can download the complete project &lt;a href="http://projectswithlove.com/projects/AustralianPostcodes.zip"&gt;AustralianPostcodes.zip&lt;/a&gt; (961kB).&lt;/blockquote&gt;

&lt;p&gt;I wrote a lot of code for this post but I've included none of it here. The code exists to make the abstract discussion about how to design a program seem less abstract &amp;mdash; I hope that you can look at the code and understand the sometimes vague statements I've made in this post.&lt;/p&gt;

&lt;p&gt;The first half of the post was about identifying the data your program has and then identifying how to build the controllers in your program to load and display this data. The purpose of going through these steps is to explain that these are the details you must have clear in your mind &lt;em&gt;before&lt;/em&gt; you start writing code. Programming requires &amp;mdash; above all else &amp;mdash; that you be able to absolutely and unambiguously clarify your idea.&lt;/p&gt;

&lt;p&gt;The second half of the post was about module-controller relationships. The purpose here is not to say Model-View-Controller is wrong but to point out that the purpose of Model-View-Controller is decoupled, reusable modules with all construction and context provided by hierarchy of lightly coupled controller objects running through the spine of your program &amp;mdash; and that this is a pattern that can be applied repeatedly (and even recursively) throughout your program, not just to views or your main model.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-1577607452936425830?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/OiRdYZLK_hU" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1577607452936425830?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1577607452936425830?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/OiRdYZLK_hU/design-of-iphone-application.html" title="The design of an iPhone application" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/12/design-of-iphone-application.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MCSH46fSp7ImA9WxNaFkg.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-1071531164284879256</id><published>2009-12-01T00:17:00.001-08:00</published><updated>2009-12-01T00:17:49.015-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-01T00:17:49.015-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Xcode" /><category scheme="http://www.blogger.com/atom/ns#" term="performance tests" /><title>There's a Garbage Collection ninja hiding in the project templates</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Not all Xcode project templates are alike. Especially the Core Data Command Line Tool...&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;An unwanted feature jumped out and attacked me!&lt;/h4&gt;
&lt;p&gt;In &lt;a href="http://cocoawithlove.com/2009/11/writing-parser-using-nsscanner-csv.html"&gt;yesterday's post on implementing a CSV parser&lt;/a&gt;, I briefly mentioned that the parser took around 0.28 seconds to parse the test data that I provided. I consider this a good time for the parser to take but my first run was not so quick.&lt;/p&gt;

&lt;p&gt;The first timing test I ran gave a parsing time of 1.15 seconds. This was slightly shocking to me, since I had already run a "control" test &amp;mdash; where I just used &lt;code&gt;componentsSeparatedByString:&lt;/code&gt; to break into lines and then into fields &amp;mdash; that took just 0.95 seconds.&lt;/p&gt;

&lt;p&gt;Had I really spent all that time writing code that was 20% slower (albeit more functional) than a clumsy, brute force approach?&lt;/p&gt;

&lt;p&gt;No. As it turns out, the Xcode Project Template I had used for the test project, the:&lt;/p&gt;

	&lt;ul&gt;Mac OS X&amp;rarr;Application&amp;rarr;Command Line Tool&amp;rarr;Type:Core Data&lt;/ul&gt;

&lt;p&gt;project has Garbage Collection enabled by default.&lt;/p&gt;

&lt;p&gt;The only real hint that this template is different is the &lt;code&gt;objc_startCollectorThread()&lt;/code&gt; line in the default &lt;code&gt;main()&lt;/code&gt; function &amp;mdash; of course, I never saw this line because I always replace the source files in the templates with my own versions that follow my own formatting style.&lt;/p&gt;

&lt;p&gt;Anyway, I turned Garbage Collection off and... &lt;em&gt;boom&lt;/em&gt; 4 times faster.&lt;/p&gt;

&lt;p&gt;I'd ask for more warning about these major &amp;mdash; but subtle &amp;mdash; changes to templates in the future but you know... ninjas, what can you do?&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-1071531164284879256?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/F5_ROm9hCDY" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1071531164284879256?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1071531164284879256?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/F5_ROm9hCDY/there-garbage-collection-ninja-hiding.html" title="There&amp;#39;s a Garbage Collection ninja hiding in the project templates" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/12/there-garbage-collection-ninja-hiding.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04BQX09fSp7ImA9WxNaFk4.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-6802269504896705867</id><published>2009-11-30T02:56:00.001-08:00</published><updated>2009-11-30T18:52:30.365-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-30T18:52:30.365-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><category scheme="http://www.blogger.com/atom/ns#" term="Core Data" /><title>Writing a parser using NSScanner (a CSV parsing example)</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Comma-separated value (CSV) files are one of the most commonly used data formats for exchanging rows of simple data. There are many implementations of CSV parsing for Cocoa strings but the purpose of this post is to use the example of an RFC4180 compliant CSV parser implementation to show you the basics of writing a recursive descent parser for importing data into your Cocoa applications.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;

&lt;p&gt;CSV parsers for Cocoa already exist: Drew McCormack at &lt;a href="http://www.macresearch.org"&gt;MacResearch&lt;/a&gt; has &lt;a href="http://www.macresearch.org/cocoa-scientists-part-xxvi-parsing-csv-data"&gt;a good article covering his implementation of a CSV parser&lt;/a&gt; and &lt;a href="http://michael.stapelberg.de/cCSVParse"&gt;cCSVParse&lt;/a&gt; will also do the job. Instead of CSV and the implementation itself, I'm going to try and focus on reading a parser grammar and adapting that into a program of your own.&lt;/p&gt;

&lt;p&gt;Most common solutions for parsing CSV files involve quick parsers which don't consider the full format and instead just split strings into lines using &lt;code&gt;-[NSString componentsSeparatedByString:@"\n"]&lt;/code&gt; and then split lines into columns with &lt;code&gt;-[NSString componentsSeparatedByString:@","]&lt;/code&gt;. This will work for some cases but it does not handle all aspects of RFC4180 and is limited to simple CSV files.&lt;/p&gt;

&lt;h4&gt;The technical description of a CSV file&lt;/h4&gt;

&lt;p&gt;Adapting slightly from &lt;a href="http://tools.ietf.org/html/rfc4180"&gt;RFC 4180 - Common Format and MIME Type for Comma-Separated Values (CSV) files&lt;/a&gt;, the Extended Backus-Naur Format (EBNF) grammar for a CSV file is as follows:&lt;/p&gt;

&lt;ul&gt;
file = [header lineSeparator] record {lineSeparator record}&lt;br/&gt;
header = name {separator name}&lt;br/&gt;
record = field {separator field}&lt;br/&gt;
name = field&lt;br/&gt;
field = escaped | nonEscaped&lt;br/&gt;
escaped = doubleQuote {textData | separator | lineSeparator | twoDoubleQuotes} doubleQuote&lt;br/&gt;
nonEscaped = textData&lt;br/&gt;
doubleQuote = '"'&lt;br/&gt;
twoDoubleQuotes = '""'&lt;br/&gt;
separator = ','&lt;br/&gt;
lineSeparator = ('\r' | '\n') {'\r' | '\n'}&lt;br/&gt;
textData = {&lt;em&gt;characters up to the next double quote character, separator string or lineSeparator&lt;/em&gt;}
&lt;/ul&gt;

&lt;p&gt;If you're not accustomed to reading EBNFs, the very first line here (the "file" line) states that a CSV "file":&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;optionally has a "header", which if used must be followed by a "lineSeparator"&lt;/li&gt;
&lt;li&gt;must have a "record"&lt;/li&gt;
&lt;li&gt;the first record may be followed by any number of "lineSeparator" plus "record" entries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The grammar shown here is slightly less restrictive than RFC4180 in that it allows any data (not just the CSV subset of US-ASCII) in the "textData". I'll also implement the parser so that different separators (including any string that contains no new line or double quote characters) can be used instead of commas. The implementation will also support Unix newlines or classic Mac carriage returns can be used instead of DOS "\r\n" line separators.&lt;/p&gt;

&lt;h4&gt;Design of the parser&lt;/h4&gt;

&lt;p&gt;The parser will be a form of &lt;a href="http://en.wikipedia.org/wiki/Recursive_descent_parser"&gt;recursive descent parser&lt;/a&gt;, which is the easiest way to implement most simple grammars like the one above. The idea is that we write a method for each line of the grammar. If any line contains a reference to another line, the implementation method will attempt to descend into the method for the referenced line.&lt;/p&gt;

&lt;p&gt;If you're accustomed to the lex/yacc school of thought and are curious to know if the approach will similarly split tokenizing and parsing into separate stages: yes, it will. Most of the tokenizing is done by &lt;code&gt;NSScanner&lt;/code&gt; (although it presents each token as requested, not as a pre-prepared stream). The code we actually implement will predominantly deal with the parser/generator side.&lt;/p&gt;

&lt;p&gt;Initialization of the parser will be handled by the following method:&lt;/p&gt;

&lt;pre&gt;- (id)initWithString:(NSString *)csvString
    separator:(NSString *)separatorString
    hasHeader:(BOOL)hasHeader
    fieldNames:(NSArray *)fieldNames;&lt;/pre&gt;

&lt;p&gt;The structure of CSV files means that it is difficult to guess if the header line is actually present &amp;mdash; so we need to tell the parser whether to look for it. An array of names for fields can be provided if there is no header (if no names are provided, they'll be given names with the format "FIELD_X").&lt;/p&gt;

&lt;p&gt;The parsing will be initiated by invoking either:&lt;/p&gt;

&lt;pre&gt;- (NSArray *)arrayOfParsedRows;&lt;/pre&gt;

&lt;p&gt;where the result is an &lt;code&gt;NSArray&lt;/code&gt; of &lt;code&gt;NSDictionary&lt;/code&gt; objects or with:&lt;/p&gt;

&lt;pre&gt;- (void)parseRowsForReceiver:(id)receiver selector:(SEL)receiverSelector;&lt;/pre&gt;

&lt;p&gt;where the method &lt;code&gt;receiverSelector&lt;/code&gt; must take a single &lt;code&gt;NSDictionary&lt;/code&gt; parameter. This second method does not return the entire result but instead sends each row as it is parsed to the receiver. It is more efficient since it does not need to keep copies of all row data.&lt;/p&gt;

&lt;h4&gt;Parser methods&lt;/h4&gt;

&lt;p&gt;There are two types of parsing methods that we need to implement:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Structural methods which don't directly access the string (&lt;code&gt;parseFile&lt;/code&gt;, &lt;code&gt;parseHeader&lt;/code&gt;, &lt;code&gt;parseRecord&lt;/code&gt;, &lt;code&gt;parseName&lt;/code&gt;, &lt;code&gt;parseField&lt;/code&gt;, &lt;code&gt;parseEscaped&lt;/code&gt;, &lt;code&gt;parseNonEscaped&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Tokenizing methods which use &lt;code&gt;NSScanner&lt;/code&gt; to access the string (&lt;code&gt;parseDoubleQuote&lt;/code&gt;, &lt;code&gt;parseTwoDoubleQuotes&lt;/code&gt;, &lt;code&gt;parseSeparator&lt;/code&gt;, &lt;code&gt;parseLineSeparator&lt;/code&gt;, &lt;code&gt;parseTextData&lt;/code&gt;)&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;I'm not going to show all of them here (you can download the full code to see them) but I will show one of each type.&lt;/p&gt;

&lt;p&gt;The tokenizing methods are the easiest. All they do is invoke &lt;code&gt;NSScanner&lt;/code&gt; methods.&lt;/p&gt;

&lt;pre&gt;- (NSString *)parseLineSeparator
{
    NSString *matchedNewlines = nil;
    [scanner
        scanCharactersFromSet:[NSCharacterSet newlineCharacterSet]
        intoString:&amp;matchedNewlines];
    return matchedNewlines;
}&lt;/pre&gt;

&lt;p&gt;The structural elements have a bit more to do but are still fairly simple. The "escaped" element in the grammar has the following structure:&lt;/p&gt;

&lt;ul&gt;doubleQuote {textData | separator | lineSeparator | twoDoubleQuotes} doubleQuote&lt;/ul&gt;

&lt;p&gt;This structure is directly reflected in its implementation &amp;mdash; it starts and ends with a check for "doubleQuote" and loops over checks for "textData", "separator", "lineSeparator" or "twoDoubleQuotes" in the middle.&lt;/p&gt;

&lt;pre&gt;- (NSString *)parseEscaped
{
    if (![self parseDoubleQuote])
    {
        return nil;
    }
    
    NSString *accumulatedData = [NSString string];
    while (YES)
    {
        NSString *fragment = [self parseTextData];
        if (!fragment)
        {
            fragment = [self parseSeparator];
            if (!fragment)
            {
                fragment = [self parseLineSeparator];
                if (!fragment)
                {
                    if ([self parseTwoDoubleQuotes])
                    {
                        fragment = @"\"";
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        
        accumulatedData = [accumulatedData stringByAppendingString:fragment];
    }
    
    if (![self parseDoubleQuote])
    {
        return nil;
    }
    
    return accumulatedData;
}&lt;/pre&gt;

&lt;p&gt;An interesting point to note is that most parsing stages return the text that they parse. However, when &lt;code&gt;parseTwoDoubleQuotes&lt;/code&gt; is used, we instead append just one double quote character, since the two double quotes is actually an escape sequence representing one.&lt;/p&gt;

&lt;h4&gt;Lookaheads&lt;/h4&gt;

&lt;p&gt;The most annoying feature to implement in a recursive descent parser is a lookahead &amp;mdash; this happens in the &lt;code&gt;parseTextData&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Lookahead is required because of my choice to accept separator strings longer than a single character. This means that the "textData" element will end with any of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;\r&lt;/li&gt;
&lt;li&gt;\n&lt;/li&gt;
&lt;li&gt;U+0085&lt;/li&gt;
&lt;li&gt;"&lt;/li&gt;
&lt;li&gt;the separator string&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Unfortunately, &lt;code&gt;NSScanner&lt;/code&gt; can't scan until it reaches one of these 5 elements. The best we can do is create a character set from the first four and the first character in the separator string and use &lt;code&gt;scanUpToCharactersFromSet:intoString:&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When scanning through text data, if we reach the first character of the separator string, we need to scan ahead and see if it is actually the whole separator string. The whole separator string will terminate the "textData" without being added, otherwise we backtrack and add the character to the existing "textData" and continue scanning.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;NSScanner&lt;/code&gt; had a &lt;code&gt;scanUpToStringFromArray:intoString:&lt;/code&gt; method, this lookahead could be avoided (or at least shifted out of our code and into &lt;code&gt;NSScanner&lt;/code&gt;). But this method does not exist and it looked like too much work to efficiently implement as part of this post.&lt;/p&gt;

&lt;h4&gt;The sample program&lt;/h4&gt;

&lt;p&gt;The sample program that I've provided uses this parser to parse a 1.7 MB CSV file containing 16,081 Australian postcode entries, names and longitude/latitudes (data from &lt;a href="http://www.sixfive.co.uk/index.cfm/2007/3/25/Geocoding-Australian-Postcodes"&gt;SixFive.co.uk&lt;/a&gt;). As results are parsed, they are entered into a Core Data SQLite file.&lt;/p&gt;

&lt;p&gt;The whole process takes about 0.47 seconds on my Mac Pro with parsing taking 0.28 seconds of this time and Core Data object creation taking 0.19 seconds. I'm sure a more carefully coded parser could halve this time or better but it represents good performance for minimal effort.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can &lt;a href="http://projectswithlove.com/projects/CSVImporter.zip"&gt;download the CSVParser class and CSVImporter sample project&lt;/a&gt; (315kB).&lt;/blockquote&gt;

&lt;p&gt;The aim in this post was to present a complete, flexible CSV parser while making the code as easy to read as possible. I hope that it has shown how you can import data from unconventional formats into Cocoa-friendly formats easily while obeying the more minor quirks that many formats have.&lt;/p&gt;

&lt;p&gt;The type of parser presented here is a recursive descent parser. This is the easiest parser to implement for simple grammars. However, this is not how commercial parsers are written &amp;mdash; larger parsers use generated action and goto tables to handle their branches instead of manually written methods and code. Have a look at the &lt;a href="http://en.wikipedia.org/wiki/LR_parser"&gt;Wikipedia entry on LR parsers&lt;/a&gt; for more on how this is done.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-6802269504896705867?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/PKfByamGTMY" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/6802269504896705867?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/6802269504896705867?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/PKfByamGTMY/writing-parser-using-nsscanner-csv.html" title="Writing a parser using NSScanner (a CSV parsing example)" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/11/writing-parser-using-nsscanner-csv.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUADR3g6eyp7ImA9WxNbGEg.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-1464593287155497194</id><published>2009-11-21T00:31:00.001-08:00</published><updated>2009-11-21T18:42:56.613-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-21T18:42:56.613-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="performance tests" /><category scheme="http://www.blogger.com/atom/ns#" term="Core Data" /><title>Performance tests: Replacing Core Data Key Paths</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In Mac OS X 10.5, Core Data switched from using &lt;code&gt;valueForKey:&lt;/code&gt; as the recommended way to access Core Data attributes and relationships to auto-generated accessor methods. This new approach is faster for fetching values but lacks &lt;code&gt;NSKeyValueCoding&lt;/code&gt;'s ability to coalesce the values extracted from every object in a "to-many" relationship in a single statement.&lt;/p&gt;

&lt;p&gt;In this post, I'll look at replacing the &lt;code&gt;NSSet&lt;/code&gt; traversal and &lt;code&gt;NSSet&lt;/code&gt; coalescing abilities offered by &lt;code&gt;NSKeyValueCoding&lt;/code&gt; with an approach that invokes accessor methods directly to see if I can bring some of the performance improvement of auto-generated accessor methods to situations involving &lt;code&gt;NSSet&lt;/code&gt; traversals.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Accessing the attributes and relationships of an NSManagedObject&lt;/h4&gt;

&lt;p&gt;In this post, I'll look at performance in a Core Data program using the following model:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SwdvxsHN1KI/AAAAAAAAAgM/_hBCynJ-8XA/modelentities.png?imgmax=800" alt="modelentities.png" border="0" width="504" height="129" /&gt;

&lt;p&gt;If you're not familiar with Core Data entity diagrams, the important point here is that every &lt;code&gt;Company&lt;/code&gt; can have multiple &lt;code&gt;Project&lt;/code&gt;s and every &lt;code&gt;Project&lt;/code&gt; can have multiple &lt;code&gt;Employee&lt;/code&gt;s&lt;/p&gt;

&lt;p&gt;Given this model, if I have a pointer, &lt;code&gt;aCompany&lt;/code&gt;, which points to one of the &lt;code&gt;Company&lt;/code&gt; objects, getting the company's name is straightforward:&lt;/p&gt;

&lt;pre&gt;NSString *companyName = aCompany.name;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;name&lt;/code&gt; property accessed here is implemented in an auto-generated accessor method that &lt;code&gt;NSManagedObject&lt;/code&gt; provides for us.&lt;/p&gt;

&lt;p&gt;Before Mac OS X 10.5, the only way of accessing values in Core Data was using key value coding:&lt;/p&gt;

&lt;pre&gt;NSString *companyName = [aCompany valueForKey:@"name"];&lt;/pre&gt;

&lt;p&gt;Why was the change away from key value coding made? The main reason was performance (although improved syntax and type-safety also helped). Fetching the name one million times using key value coding takes 0.284016 seconds but using the auto-generated property accessor method this drops to 0.109017 seconds &amp;mdash; 2.6 times faster.&lt;/p&gt;

&lt;h4&gt;Set traversal&lt;/h4&gt;

&lt;p&gt;But key-value coding (the "old" method) still has one important advantage over the auto-generated methods: it's quicker when traversing a set returned from a 'to-many' relationship.&lt;/p&gt;

&lt;p&gt;For example, if I want to get the full set of &lt;code&gt;Project&lt;/code&gt; names used by &lt;code&gt;aCompany&lt;/code&gt; it is easy with Key Value Coding:&lt;/p&gt;

&lt;pre&gt;NSSet *projectNames = [aCompany valueForKeyPath:@"projects.name"];&lt;/pre&gt;

&lt;p&gt;This works because the &lt;code&gt;NSSet&lt;/code&gt; implementation of the &lt;code&gt;NSKeyValueCoding&lt;/code&gt; protocol automatically traverses into itself to get the names for each &lt;code&gt;Project&lt;/code&gt; object it contains.&lt;/p&gt;

&lt;p&gt;Using the accessor methods, the na&amp;iuml;ve equivalent would be:&lt;/p&gt;

&lt;pre&gt;NSMutableSet *result = [NSMutableSet set];
for (Project *project in aCompany.projects)
{
    NSString *name = project.name;
    if (value)
    {
        [result addObject:value];
    }
}&lt;/pre&gt;

&lt;p&gt;Not only is this more code than the key value coding approach but it is actually &lt;em&gt;slower&lt;/em&gt;. For 10,000 Company objects, each with 100 Project objects, the key value coding approach took 0.25692 seconds and the na&amp;iuml;ve approach using auto-generated accessors took 0.52873 seconds.&lt;/p&gt;

&lt;p&gt;The new and improved approach has gone from 2.6 times faster to 2 times slower.&lt;/p&gt;

&lt;h4&gt;Fixing the speed problems&lt;/h4&gt;

&lt;h5&gt;The old method got faster&lt;/h5&gt;

&lt;p&gt;Before I get to why the "new" method was slower, the first point to notice is that the key value coding approach (the "old" approach) was actually &lt;em&gt;faster&lt;/em&gt; when using set traversal. Despite the extra work involved in traversing from the &lt;code&gt;Company&lt;/code&gt; to the &lt;code&gt;Project&lt;/code&gt; and uniquing the names to form a single &lt;code&gt;NSSet&lt;/code&gt;, the key value coding took just 0.25692 seconds to fetch one million &lt;code&gt;Project&lt;/code&gt; names, down from the 0.284016 seconds to fetch one million &lt;code&gt;Company&lt;/code&gt; names.&lt;/p&gt;

&lt;p&gt;This isn't a glitch; despite more work involved, Key Value Coding improves its performance when sets are iterated internally (as part of the key path) rather than externally (as I did when iterating over one million &lt;code&gt;Company&lt;/code&gt; objects).&lt;/p&gt;

&lt;p&gt;Despite its improvements, we should still be able to beat Key Value Coding with our approach using the auto-generated accessor methods but the margin is obviously going to be a lot closer than it was for the &lt;code&gt;aCompany.name&lt;/code&gt; iteration..&lt;/p&gt;

&lt;h5&gt;Fixing the new method&lt;/h5&gt;

&lt;p&gt;Basic profiling quickly reveals that the problems here have little to do with the actual property accessors. The slow speed is primarily due to &lt;code&gt;addObject:&lt;/code&gt;

&lt;p&gt;After looking at the private methods on the stack in the profiler, it became clear that the reason was reallocation. Every time the &lt;code&gt;NSMutableSet&lt;/code&gt; needed to grow in size, it was reallocating its internal storage, resulting in the poor performance.&lt;/p&gt;

&lt;p&gt;We can pre-allocate the entire set based on the worst-case size (all Project names unique). The code then becomes:&lt;/p&gt;

&lt;pre&gt;NSSet *projects = aCompany.projects;
NSMutableSet *result = [NSMutableSet setWithCapacity:[projects count]];
for (Project *project in projects)
{
    NSString *name = project.name;
    if (value)
    {
        [result addObject:value];
    }
}&lt;/pre&gt;

&lt;p&gt;Success! This version now runs in 0.19104 seconds (down from 0.52873 seconds) and is now 25% faster than the key value coding approach.&lt;/p&gt;

&lt;p&gt;We're no longer 2.6 times faster but &lt;code&gt;NSSet&lt;/code&gt;'s internal implementation of Key Value Coding has some advantages over us here: since it has internal access to the storage, it can optimize the iteration over the "to-many" relationship and the building of the new set more than we can.&lt;/p&gt;

&lt;h4&gt;A category implementation&lt;/h4&gt;

&lt;p&gt;To reuse the above approach in future, we can implement a category on &lt;code&gt;NSSet&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There will be two methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;objectValuesForProperty:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;coalescedValuesForProperty:&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first will implement the previously mentioned example (where the &lt;code&gt;NSSet&lt;/code&gt; contains basic objects).&lt;/p&gt;

&lt;p&gt;The second will replicate the Key Value Coding operator &lt;code&gt;@distinctUnionOfSets&lt;/code&gt; (to handle the case where the &lt;code&gt;NSSet&lt;/code&gt; contains an &lt;code&gt;NSSet&lt;/code&gt; and you need to coalesce the objects inside the child sets).&lt;/p&gt;

&lt;p&gt;An example of this second case is getting all the &lt;code&gt;Employee&lt;/code&gt; objects at a &lt;code&gt;Company&lt;/code&gt;. In Key Value Coding we would write:&lt;/p&gt;

&lt;pre&gt;NSSet *allEmployees = [aCompany valueForKeyPath:@"projects.@distinctUnionOfSets.employees"];&lt;/pre&gt;

&lt;p&gt;With the &lt;code&gt;coalescedValuesForProperty:&lt;/code&gt; method, we could write:&lt;/p&gt;

&lt;pre&gt;NSSet *allEmployees = [aCompany.projects coalescedValuesForProperty:@selector(employees)];&lt;/pre&gt;

&lt;p&gt;The implementation is then:&lt;/p&gt;

&lt;pre&gt;#import &amp;lt;objc/message.h&amp;gt;

@implementation NSSet (PropertyCoalescing)

- (NSSet *)objectValuesForProperty:(SEL)propertySelector
{
    NSMutableSet *result = [NSMutableSet setWithCapacity:[self count]];
    for (id object in self)
    {
        id value = objc_msgSend(object, propertySelector);
        if (value)
        {
            [result addObject:value];
        }
    }
    return result;
}

- (NSSet *)coalescedValuesForProperty:(SEL)propertySelector
{
    NSInteger count = 0;
    for (id object in self)
    {
        count += [objc_msgSend(object, propertySelector) count];
    }
    NSMutableSet *result = [NSMutableSet setWithCapacity:count];
    for (id object in self)
    {
        id value = objc_msgSend(object, propertySelector);
        if (value)
        {
            [result unionSet:value];
        }
    }
    return result;
}

@end&lt;/pre&gt;

&lt;p&gt;With the &lt;code&gt;coalescedValuesForProperty:&lt;/code&gt; method we iterate over the whole set twice to get the size but this remains the fastest option &amp;mdash; in fact, this method is about 35% faster than the Key Value Coding approach compared to &lt;code&gt;objectValuesForProperty:&lt;/code&gt;'s 25% improvement.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;By request, here's the code used in the testing: &lt;a href="http://projectswithlove.com/projects/PropertyAccessors.zip"&gt;PropertyAccessors.zip&lt;/a&gt; (32kB). It's hastily thrown together to accompany this post, so it's not necessarily well written but it's there if you're interested.&lt;/blockquote&gt;

&lt;p&gt;I wrote this code and ran these performance tests because I have a lot of code that uses Key Value Coding for traversing "to-many" relationships. I was concerned that since Core Data advocates the use of the auto-generated accessor methods for performance reasons, that my use of key value coding in these cases would be significantly slower than it should be.&lt;/p&gt;

&lt;p&gt;The result is that while it is possible to improve upon the performance of Key Value Coding for traversing sets in Core Data, the improvement is only 25-35%, not the 260% improvement from replacing Key Value Coding for individual property access. Key Value Coding is quite efficient when dealing with sets &amp;mdash; certainly more efficient than it is when accessing single properties.&lt;/p&gt;

&lt;p&gt;Of course, the 35% speed improvement offered by the approach presented here will certainly be beneficial in performance critical areas.&lt;/p&gt;

&lt;p&gt;With regards to the implementation itself: never underestimate the performance impact of keeping memory reallocations at a minimum. Starting with a zero capacity &lt;code&gt;NSSet&lt;/code&gt; and continually growing it using &lt;code&gt;addObject:&lt;/code&gt; was 3 times slower than allocating once.&lt;/p&gt;

&lt;p&gt;The capacity of the &lt;code&gt;NSMutableSet&lt;/code&gt; allocated is large enough to hold all objects but if the objects are not all unique, this will be bigger than required. If this extra memory usage is a concern, you can copy the set once it is generated. The copy will be only as big as strictly required and you can release the original. The drawback is that this copying process will add another 10-15% onto the time taken.&lt;/p&gt;

&lt;/span&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-1464593287155497194?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/bLPBNEd1zKE" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1464593287155497194?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1464593287155497194?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/bLPBNEd1zKE/performance-tests-replacing-core-data.html" title="Performance tests: Replacing Core Data Key Paths" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/11/performance-tests-replacing-core-data.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMCRH05fCp7ImA9WxNbE04.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-4640680279119739793</id><published>2009-11-14T04:45:00.001-08:00</published><updated>2009-11-15T17:21:05.324-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-15T17:21:05.324-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><category scheme="http://www.blogger.com/atom/ns#" term="fun hacks" /><title>A drop-in fix for the problems with NSHost</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;As pointed out by Mike Ash in his recent &lt;a href="http://mikeash.com/?page=pyblog/friday-qa-2009-11-13-dangerous-cocoa-calls.html"&gt;Friday Q&amp;A 2009-11-13: Dangerous Cocoa Calls&lt;/a&gt;, &lt;code&gt;NSHost&lt;/code&gt; is not thread-safe for use outside of the main thread and due to potentially slow, synchronous network access is not really suitable for use on the main thread either. Fortunately, in Cocoa there are often ways to transparently fix classes that don't work as they should. In this post, I'll show you how you can transparently patch &lt;code&gt;NSHost&lt;/code&gt; using a drop-in solution and provide a non-blocking solution for &lt;code&gt;NSHost&lt;/code&gt; lookups.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;NSHost&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;&lt;a href="http://developer.apple.com/mac/library/documentation/cocoa/reference/foundation/Classes/NSHost_Class/index.html"&gt;NSHost&lt;/a&gt;&lt;/code&gt; is a class with a simple API that fetches the names or addresses of an internet host. You can use it to perform DNS lookups but one of the primary uses is to get the name and address of the current host.&lt;/p&gt;

&lt;p&gt;All calls to &lt;code&gt;NSHost&lt;/code&gt; are synchronous &amp;mdash; they block until the response is fetched. If a network error occurs, this could result in a 60 second delay before a timeout response occurs &amp;mdash; definitely not something you want to do in your main thread.&lt;/p&gt;

&lt;p&gt;Unfortunately, according to &lt;a href="http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html"&gt;Cocoa's Thread Safety Summary&lt;/a&gt;, &lt;code&gt;NSHost&lt;/code&gt; is not thread-safe &amp;mdash; so we can't simply pass the functionality off to another thread.&lt;/p&gt;

&lt;p&gt;Does this mean you must revert to &lt;code&gt;NSHost&lt;/code&gt;'s CoreFoundation equivalent, &lt;code&gt;CFHost&lt;/code&gt;, which is explicitly thread-safe? Not necessarily.&lt;/p&gt;

&lt;h4&gt;The problems we need to fix&lt;/h4&gt;

&lt;p&gt;It is not the &lt;code&gt;NSHost&lt;/code&gt; objects themselves that are the problem. &lt;code&gt;NSHost&lt;/code&gt; objects are immutable once allocated and immutable objects are implicitly thread-safe for most purposes.&lt;/p&gt;

&lt;p&gt;The problem is the cache of &lt;code&gt;NSHost&lt;/code&gt; objects maintained internally by &lt;code&gt;NSHost&lt;/code&gt; when any of the lookups are called &amp;mdash; access to this cache is unprotected from the perils of threading.&lt;/p&gt;

&lt;p&gt;In addition to this, we need to be able to perform &lt;code&gt;NSHost&lt;/code&gt; lookups asynchronously.&lt;/p&gt;

&lt;h4&gt;Design of the solution&lt;/h4&gt;

&lt;p&gt;The key consideration in these changes will be a totally drop-in solution &amp;mdash; &lt;code&gt;NSHost&lt;/code&gt; will immediately and transparently become thread-safe. No further code will be required.&lt;/p&gt;

&lt;p&gt;The solution to the threading problem will be to create a corresponding category method for every class method of &lt;code&gt;NSHost&lt;/code&gt; which wraps all calls to &lt;code&gt;NSHost&lt;/code&gt; in a &lt;code&gt;@synchronized&lt;/code&gt; section and then in the &lt;code&gt;load&lt;/code&gt; method for the category, swizzle each of these corresponding methods into the place of the original method.&lt;/p&gt;

&lt;p&gt;The asynchronous invocations can then be handled like any other asynchronous operation &amp;mdash; by spawning a new thread which will call back when complete.&lt;/p&gt;

&lt;h4&gt;Swizzling alternate implementations&lt;/h4&gt;

&lt;p&gt;If you don't know what I meant by "swizzle", what we need to do is replace the existing implementations of the &lt;code&gt;NSHost&lt;/code&gt; class methods with our own implementations. The code for doing this is as follows:&lt;/p&gt;

&lt;pre&gt;static void SwizzleClassMethods(Class class, SEL firstSelector, SEL secondSelector)
{
    Method firstMethod = class_getClassMethod(class, firstSelector);
    Method secondMethod = class_getClassMethod(class, secondSelector);
    if (!firstMethod || !secondMethod)
    {
        NSLog(@"Unable to swizzle class methods for selectors %@ and %@ on class %@",
            NSStringFromSelector(firstSelector),
            NSStringFromSelector(secondSelector),
            NSStringFromClass(class));
        return;
    }
    
    method_exchangeImplementations(firstMethod, secondMethod);
}&lt;/pre&gt;

&lt;p&gt;Then, in the &lt;code&gt;load&lt;/code&gt; method for our category...&lt;/p&gt;

&lt;pre&gt;@implementation NSHost (ThreadSafety)

+ (void)load
{
    SwizzleClassMethods(self, @selector(currentHost), @selector(threadSafeCurrentHost));
    SwizzleClassMethods(self, @selector(hostWithName:), @selector(threadSafeHostWithName:));
    SwizzleClassMethods(self, @selector(hostWithAddress:), @selector(threadSafeHostWithAddress:));
    SwizzleClassMethods(self, @selector(isHostCacheEnabled), @selector(threadSafeIsHostCacheEnabled));
    SwizzleClassMethods(self, @selector(setHostCacheEnabled:), @selector(threadSafeSetHostCacheEnabled:));
    SwizzleClassMethods(self, @selector(flushHostCache), @selector(threadSafeFlushHostCache));
    SwizzleClassMethods(self, @selector(_fixNSHostLeak), @selector(threadSafe_fixNSHostLeak));
}

// category continues...&lt;/pre&gt;

&lt;p&gt;What this does is swaps in our new implementations, (e.g. &lt;code&gt;threadSafeCurrentHost&lt;/code&gt;) in place of Apple's original implementation (e.g. &lt;code&gt;currentHost&lt;/code&gt;). Once this is done, any call to &lt;code&gt;currentHost&lt;/code&gt; will result in our new code getting executed. Similarly, the original code that we replaced is now reachable by calling &lt;code&gt;threadSafeCurrentHost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The implementation of each of these thread-safe methods takes the form:&lt;/p&gt;

&lt;pre&gt;+ (id)threadSafeCurrentHost
{
    @synchronized(self)
    {
        return [self threadSafeCurrentHost];
    }
}&lt;/pre&gt;

&lt;p&gt;This may look like the method is just calling itself but remember, after swizzling, the call to &lt;code&gt;threadSafeCurrentHost&lt;/code&gt; will actually invoke the original &lt;code&gt;currentHost&lt;/code&gt; code. So this method is actually running the original code but inside a &lt;code&gt;@synchronized&lt;/code&gt; section to maintain thread safety.&lt;/p&gt;

&lt;h4&gt;Asynchronous lookup&lt;/h4&gt;

&lt;p&gt;The best way to perform an asynchronous lookup, now that &lt;code&gt;NSHost&lt;/code&gt; will work in a thread-safe manner, is simply to perform the lookup in an &lt;code&gt;NSOperation&lt;/code&gt; and have that operation call back when done.&lt;/p&gt;

&lt;p&gt;To do this, the ThreadSafety category also adds the methods:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;code&gt;currentHostInBackgroundForReceiver:selector:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hostWithName:inBackgroundForReceiver:selector:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hostWithAddress:inBackgroundForReceiver:selector:&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;to perform lookups and call back when done. These methods take the following form:&lt;/p&gt;

&lt;pre&gt;+ (void)hostWithName:(NSString *)name
    inBackgroundForReceiver:(id)receiver
    selector:(SEL)receiverSelector
{
    [[self hostLookupQueue]
        addOperation:
            [[HostLookupOperation alloc]
                initWithReceiver:receiver
                receiverSelector:receiverSelector
                receivingThread:[NSThread currentThread]
                lookupSelector:@selector(hostWithName:)
                lookupParameter:name]];
}&lt;/pre&gt;

&lt;p&gt;and the implementation of the &lt;code&gt;HostLookupOperation&lt;/code&gt;'s &lt;code&gt;main&lt;/code&gt; method is extremely simple:&lt;/p&gt;

&lt;pre&gt;- (void)main
{
    [receiver
        performSelector:receiverSelector
        onThread:receivingThread
        withObject:[NSHost performSelector:lookupSelector withObject:parameter]
        waitUntilDone:NO];
}&lt;/pre&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can &lt;a href="http://projectswithlove.com/projects/NSHost_ThreadedAdditions.zip"&gt;download the complete code for &lt;code&gt;NSHost+ThreadedAdditions&lt;/code&gt;&lt;/a&gt; (3kB).&lt;/blockquote&gt;

&lt;p&gt;The main advantage of this approach shown here is that you only need to add the files to your project &amp;mdash; you do not need to add or change any other code to make this work.&lt;/p&gt;

&lt;p&gt;These additions provide reasonably good thread safety for &lt;code&gt;NSHost&lt;/code&gt; as they channel all use of the class through the thread-safe wrapping methods. The limitation to this is that Apple could add further methods in the future that circumvent the &lt;code&gt;@synchonized&lt;/code&gt; sections we've added and the thread safety would be breached until swizzled methods were added for these new methods.&lt;/p&gt;

&lt;p&gt;On the immutability of &lt;code&gt;NSHost&lt;/code&gt; instances &amp;mdash; technically, the private instance variables &lt;code&gt;names&lt;/code&gt; and &lt;code&gt;addresses&lt;/code&gt; of &lt;code&gt;NSHost&lt;/code&gt; are allocated mutable but experimentally, I have verified that they are never mutated (in fact, there are no methods on &lt;code&gt;NSHost&lt;/code&gt; that would do this). However, &lt;code&gt;localizedName&lt;/code&gt;, available in Mac OS X 10.6, uses data from outside &lt;code&gt;NSHost&lt;/code&gt; so might not be thread-safe.&lt;/p&gt;

&lt;p&gt;In reality, you can avoid all of this code and simply use the &lt;code&gt;CFHost&lt;/code&gt; API to achieve the same benefits. This &lt;code&gt;ThreadedAdditions&lt;/code&gt; category for &lt;code&gt;NSHost&lt;/code&gt; is an effort to continue using the simpler API of &lt;code&gt;NSHost&lt;/code&gt; and at the same time, to demonstrate that just because Apple's implementation of something is not thread-safe in its internal implementation, doesn't mean you can't make it thread-safe in the greater context of your whole program.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-4640680279119739793?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/Jlr-oiXrs44" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/4640680279119739793?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/4640680279119739793?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/Jlr-oiXrs44/drop-in-fix-for-problems-with-nshost.html" title="A drop-in fix for the problems with NSHost" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/11/drop-in-fix-for-problems-with-nshost.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIER38-eSp7ImA9WxNbF0U.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-5498576471595968227</id><published>2009-11-06T22:59:00.001-08:00</published><updated>2009-11-20T23:28:26.151-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-20T23:28:26.151-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="graphics" /><title>Creating iPhone and Mac icons using Inkscape (Part 2 of 2)</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In this part, I expand on the simple techniques presented in the first part by adding different line, effect and texture styles. I'll also present some Mac application icons and simple texturing.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Introduction&lt;/h4&gt;

&lt;p&gt;This series covers the creation of the following different icon styles:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvAqo04PsPI/AAAAAAAAAeg/d5Pvuu0d24I/all-icons.png?imgmax=800" alt="all-icons.png" border="0" width="550" height="111" /&gt;

&lt;p&gt;The first icon was created in the first part of the series. I'll go through the creation of the remaining variations on the checkbox/checkmark theme in this post.&lt;/p&gt;

&lt;p&gt;I'll assume that you've read the first part or are familiar with the techniques involved.&lt;/p&gt;

&lt;h4&gt;Icon 2: A brighter, more colorful iPhone icon&lt;/h4&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvUZp6qZJ2I/AAAAAAAAAf4/hj-veh__ZvE/icon2.png?imgmax=800" alt="icon2.png" border="0" width="147" height="146" style="float:right;padding-top:20px;padding-left:20px;padding-bottom:20px;"/&gt;

&lt;h5&gt;Goals in this section&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Use a radial gradient&lt;/li&gt;
&lt;li&gt;Learn to adjust all of the common stroke properties&lt;/li&gt;
&lt;li&gt;Learn to adjust a multi-effect filter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The icon developed in Part 1 is very simple &amp;mdash; really just a couple white lines over a typical iPhone icon background &amp;mdash; which is appropriate for a serious application but might not stand out as prominently against other icons.&lt;/p&gt;

&lt;p&gt;In this variation, I'll have the background reach a bright point behind the checkbox element and change the effect on the lines so that the lines look embossed into this bright point &amp;mdash; visually integrating the background and the overlayed element.&lt;/p&gt;

&lt;p&gt;I'll also introduce a complimentary (opposite hues) color scheme with an azure blue and a red.&lt;/p&gt;

&lt;h5&gt;A radial background&lt;/h5&gt;

&lt;p&gt;Starting with a 57x57 document as created in Part 1, add a rectangle filling the document area.&lt;/p&gt;

&lt;p&gt;Set the fill to a radial fill and edit the gradient. In the Gradient Editor, click "Add Stop" twice to make the gradient a four part gradient. Top to bottom, the four gradient colors should be:

&lt;ol&gt;&lt;li&gt;RGBA=(192,255,250,255)&lt;/li&gt;
&lt;li&gt;RGBA=(99,164,184,255), Offset 0.26&lt;/li&gt;
&lt;li&gt;RGBA=(5,74,119,255), Offset 0.62&lt;/li&gt;
&lt;li&gt;RGBA=(0,40,80,255)&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;We now have a bright spot in the center of the background.&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvTkpP4P15I/AAAAAAAAAeo/IHV0VUh7340/blue-dot.png?imgmax=800" alt="blue-dot.png" border="0" width="300" height="301" /&gt;

&lt;p&gt;Over the top of this, paste (or recreate) the starburst effect from Part &amp;mdash; X,Y=(-15.7,-15.7) should center it perfectly.&lt;/p&gt;

&lt;p&gt;In the Fill and Stroke palette, set the opacity of the starburst to 100%.&lt;/p&gt;

&lt;p&gt;Now, to make the starburst smoother, open the Filter Editor (from the Filters menu) and find the starburst's blur effect (it should be selected in the filter column when the starburst itself is selected). Select the Gaussian Blur effect and set the standard deviation to 0.75.&lt;/p&gt;

&lt;h5&gt;Different stroke properties for the checkbox and checkmark&lt;/h5&gt;

&lt;p&gt;Create the checkbox and checkmark in the same way that they were created in the first part or copy them in. If you copy them in, select both the checkbox and the checkmark and choose Filters&amp;rarr;Remove Filters to remove the shadow and bevel effect applied in the first part.&lt;/p&gt;

&lt;p&gt;Remove the corner radius from the checkbox (select it using the rectangle tool and set the Rx and Ry to zero). In the Fill and Stroke Editor, select the Stroke Style Tab and set the Line Width to 4.0 "px" and the Join Style to rounded. The result of these steps is to create a slightly thicker line that is curved on the corners within its width.&lt;/p&gt;

&lt;p&gt;Select the checkmark and set the stroke color to RGBA=(255,42,42,255) and the stroke width to 4.0 "px".&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvTrY2F85DI/AAAAAAAAAes/_d473sRTlp8/altered-strokes.png?imgmax=800" alt="altered-strokes.png" border="0" width="377" height="367" /&gt;

&lt;h5&gt;A customized "Cutout glow"&lt;/h5&gt;

&lt;p&gt;With both checkbox and checkmark selected, choose Filters&amp;rarr;Shadows and Glows&amp;rarr;Cutout Glow. Go to the Filter Editor and find this Cutout Glow filter. This filter will have 5 effect rows. Select the Offset row and set the X,Y offset to (0.8,0.8). Select the Gaussian Blur row and set the Standard Deviation to 1.0.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/SvTsJwuhnzI/AAAAAAAAAew/GQ5SZnlfRPg/cutout-glow.png?imgmax=800" alt="cutout-glow.png" border="0" width="550" height="310" /&gt;

&lt;p&gt;Now follow the instructions from the "Apply the gloss effect and round corners" subsection of the previous post to complete the icon.&lt;/p&gt;

&lt;h4&gt;Icon 3: A cartoonish style&lt;/h4&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvUZ7a7Ft8I/AAAAAAAAAf8/Y0pMEqkFvyU/icon3.png?imgmax=800" alt="icon3.png" border="0" width="148" height="146" style="float:right;padding-top:20px;padding-left:20px;padding-bottom:20px;"/&gt;

&lt;h5&gt;Goals in this section&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Directly edit paths for greater control&lt;/li&gt;
&lt;li&gt;See a Path Effect (Spiro Spline) in action&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This variation will forego the starburst effect and instead go for a smoother, more "cartoonish" approach. The checkbox and checkmark will then need to be more distinctive as they will be the only significant graphical elements&lt;/p&gt;

&lt;h5&gt;Creating a path&lt;/h5&gt;

&lt;p&gt;Start with the background rectangle from the "brighter, more colorful iPhone icon" created above (if you created a cloned version for the round corners, don't copy the cloned version as it will behave strangely).&lt;/p&gt;

&lt;p&gt;Select the Bezier Path tool (11th icon down in the Tool Area). We'll draw the rough loop first.&lt;/p&gt;

&lt;p&gt;You can use the Bezier Path tool in one of two ways: simple click-and-release to create corner points and straight line segments or click and drag to create curve points (the dragging then affects the curvature of each point).&lt;/p&gt;

&lt;p&gt;For simplicity here, I'll show you how to create the path using corner points and we'll apply the curve as a second step. When you're more comfortable with the Bezier Tool, this can be done as a single step.&lt;/p&gt;

&lt;p&gt;Create a point at the 12 o'clock position, then 9, 6, 3 and then underneath the original 12. Then another inside the second twelve and then inside the 3, 6, 9, and between the first and second 12's. Then close the path by clicking on the first point.&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvTwNZ2Uf7I/AAAAAAAAAe0/sI3PK7-FSq8/stroke-creation.png?imgmax=800" alt="stroke-creation.png" border="0" width="500" height="241" /&gt;

&lt;blockquote&gt;&lt;strong&gt;Bezier path creation&lt;/strong&gt;: If you make a mistake with the path, you can either fix it later or press escape to cancel the whole path. Pressing the return-key will end the path without closing it.&lt;/blockquote&gt;

&lt;h5&gt;Adjusting path control point properties&lt;/h5&gt;

&lt;p&gt;Using the Node Tool (2nd icon down in the Tool Area) ensure the path you just created is selected. Drag a selection box around the nodes at 3, 6 and 9 o'clock (don't select the nodes at 12 o'clock). In the toolbar at the top, select the "Make selected nodes smooth" button (should be 8th from the left in the toolbar immediately above the window).&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvTxDs_IToI/AAAAAAAAAe4/wGYYUbr8mX0/smooth-points.png?imgmax=800" alt="smooth-points.png" border="0" width="300" height="309" /&gt;

&lt;h5&gt;Applying a path effect&lt;/h5&gt;

&lt;p&gt;Leaving the path selected, choose the Path&amp;rarr;Path Effect Editor menu item. In the Path Effect Editor palette, select "Spiro Spline" from the popup menu and click the "Add" button. The "Spiro Spline" is an effect that makes smooth curved paths much easier than regular Bezier curves.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/SvTxbYCbAWI/AAAAAAAAAe8/9CnV7Lk-bkk/spiro-spline.png?imgmax=800" alt="spiro-spline.png" border="0" width="400" height="299" /&gt;

&lt;p&gt;Once this is done, you can tweak the nodes in the path (using the Node Tool) until it is the exact shape desired.&lt;/p&gt;

&lt;p&gt;In the Fill and Stroke Editer, remove any stroke, apply a faded yellow to faded orange linear gradient fill from left to right across the checkbox loop and it is done.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/SvTyBrC-f0I/AAAAAAAAAfA/nLLF9j_m60I/checkbox-loop.png?imgmax=800" alt="checkbox-loop.png" border="0" width="300" height="302" /&gt;

&lt;h5&gt;Stroke to path&lt;/h5&gt;

&lt;p&gt;Create the checkmark as for the previous icons but set the Stroke Width to 6 "px" and the Style Join and Cap to square corners. With the path selected, choose the menu item Path&amp;rarr;Stroke to Path. This will turn the line into a filled path. Set the stroke of this path to "no stroke" and set the fill to an orange to red linear gradient fill from left to right across the checkmark.&lt;/p&gt;

&lt;p&gt;Now we need to adjust the checkmark to have a looser aesthetic. Select the Node Tool and the checkmark. Drag the lines in the short stem upwards slightly and the lines in the long stem inwards slightly. Adjust the control points at the ends of each stem so that they are flared outwards a 
little.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/SvUYe-Go6RI/AAAAAAAAAfw/p7d7XnITuzo/checkmark-adjustment.png?imgmax=800" alt="checkmark-adjustment.png" border="0" width="381" height="400" /&gt;

&lt;p&gt;Follow the instructions from "Bevel effect and shadow" from Part 1 to apply these effects. Follow the instructions from the "Apply the gloss effect and round corners" subsection of the previous post to complete the icon.&lt;/p&gt;

&lt;h4&gt;Icon 4: A document-based Mac icon&lt;/h4&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvUaMmdeOWI/AAAAAAAAAgA/MPNcEaQXki8/icon4.png?imgmax=800" alt="icon4.png" border="0" width="179" height="182" style="float:right;padding-top:20px;padding-left:20px;padding-bottom:20px;"/&gt;

&lt;h5&gt;Goals in this section&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;See the common components of a Mac document-based application icon&lt;/li&gt;
&lt;li&gt;Use multiple overlapping gradients to achieve softer gradients&lt;/li&gt;
&lt;li&gt;Add a texture to a background by filling with text&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In terms of colors and effects, Mac icons tend to be far more subdued than iPhone icons. Where iPhone icons are only shown on the Home screen but are small and need to stand out, Mac icons may sit in the Dock for extended periods and shouldn't be distracting during this time.&lt;/p&gt;

&lt;p&gt;For this reason, Mac icon colors tend to be slightly more subdued than iPhone icon colors and are frequently much lighter overall.&lt;/p&gt;

&lt;p&gt;While Mac icons are typically larger (an average of around 64x64) they can also be shown at smaller resolutions. The approach to satisfying the size range is normally to compose the icon from two key parts:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;An object or item that is easily recognizable in silhouette or at small sizes&lt;/li&gt;
&lt;li&gt;Texture or subtler elements that fade away at smaller sizes but add structure and context at larger sizes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mac icons must also handle a range of different background colors as they may be shown against people's desktop backgrounds, white folder backgrounds or against the near black of a vertical Dock. To achieve good contrast against the background, most icons are generally light in color but with a subtle shadow behind them &amp;mdash; not for 3D effect but to contrast with lighter backgrounds. Many icons also incorporate a frame or boundary into the representation which further adds to the strength of the icon's silhouette.&lt;/p&gt;

&lt;h5&gt;A rotated background&lt;/h5&gt;

&lt;p&gt;To start the icon, create a 64x64 px document. This size will help us optimize for the expected screen resolution.&lt;/p&gt;

&lt;p&gt;Into this, draw a 44 by 50 rectangle. Give it an azure to deep blue linear gradient from left to right and a white 3px stroke.&lt;/p&gt;

&lt;p&gt;Using the Selection Tool (first in the Tool Area), select the rectangle. Initially, this will show the resizing arrows around the shape. Click a second time to switch these arrows to the rotating arrows (don't double click as that will switch to the Node Tool). Click and drag one of the corner arrows to rotate the rectangle by 8&amp;deg; (the rotated angle should be visible in the status bar at the bottom of the window while dragging but the exact angle isn't important).&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvT1-mjrgPI/AAAAAAAAAfI/bExN4UjjBw0/rotated-gradient.png?imgmax=800" alt="rotated-gradient.png" border="0" width="272" height="271" /&gt;

&lt;h5&gt;Some effects and another gradient&lt;/h5&gt;

&lt;p&gt;On its own, a single gradient isn't a very impressive effect. The trick in making a background effect that is both attractive and subtle, is normally to layer a few different effects on top of each other.&lt;/p&gt;

&lt;p&gt;With the rectangle selected, select "Path"&amp;rarr;"Union". This may seem like a weird thing to do but it actually recreates the object using a path at the rotated orientation. We do this because Effects in Inkscape (like the shadow we're just about to apply) look bad (pixelated) when rotated. Recreating the object at this rotation means the effect will not have a rotation applied.&lt;/p&gt;

&lt;p&gt;Copy and paste this rotated rectangle and put the copy next to the original. Apply a drop shadow to the original with 50% opacity, Offset of (1,1) and radius of 1.5.&lt;/p&gt;

&lt;p&gt;Now remove the stroke from the copy. You'll notice that without the white stroke covering 1.5 px of the copy, the gradient region of the copy actually looks slightly bigger than the original. We need this shape to be the same size as the colored area of the original, so use the Selection Tool and with the rezize arrows, adjust the two to match (set the color to a flat fill like red and overlap the two objects to make it easier).&lt;/p&gt;

&lt;p&gt;Now set the second object to have a top to bottom (parallel to its rotated axis) linear gradient fill with four color points:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;RGBA=(168,247,249,255)&lt;/li&gt;
&lt;li&gt;RGBA=(144,198,215,0), Offset 0.30&lt;/li&gt;
&lt;li&gt;RGBA=(95,144,175,0), Offset 0.70&lt;/li&gt;
&lt;li&gt;RGBA=(18,49,106,255)&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Since this second gradient is transparent in the middle, it will show the first gradient in varying amounts through the middle. Overlapping the two should result in a softer gradient that vaguely resembles diffuse lighting across a slightly convex surface.&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvT-EZgdikI/AAAAAAAAAfQ/TRbyiJqkCOY/second-gradient.png?imgmax=800" alt="second-gradient.png" border="0" width="266" height="267" /&gt;

&lt;h5&gt;A light text-based texture&lt;/h5&gt;

&lt;p&gt;The formatting of the following paragraph is not an mistake.&lt;/p&gt;

&lt;ul&gt;As indicated before, it&lt;br/&gt;helps to add a texture to&lt;br/&gt;your Mac icons. It is best&lt;br/&gt;if you have a texture or&lt;br/&gt;image that is related to&lt;br/&gt;your application &amp;mdash; for&lt;br/&gt;this icon I don't really&lt;br/&gt;have an application, so&lt;br/&gt;I'm going to use a block&lt;br/&gt;of arbitrary text (this&lt;br/&gt;paragraph, in fact).&lt;/ul&gt;

&lt;p&gt;The Text Tool is two icons above the Gradient Tool. Click on the document to create a text object and type the text shown and formatted as above. With the text object selected, choose the Zapfino font from the font popup menu in the top toolbar. I like Zapfino because when zoomed out, it seems ornate and indistinct.&lt;/p&gt;

&lt;p&gt;Now use the Selection Tool to scale and position the text object over the other gradient rectangles.&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvT-7D2tuhI/AAAAAAAAAfU/hCngBR1JQ3g/text.png?imgmax=800" alt="text.png" border="0" width="373" height="372" /&gt;

&lt;p&gt;To add a gloss effect over everything, create a 53 by 28 rectangle, with a flat RGBA=(255,255,255,60) fill and no stroke and rotate and position it over the top half of the existing shapes.&lt;/p&gt;

&lt;h5&gt;The "representative" element&lt;/h5&gt;

&lt;p&gt;For the representative element, I'll use a checkmark in an orange circle. Create a checkmark line (same as in previous icons) set a white 5 px stroke on the checkmark.&lt;/p&gt;

&lt;p&gt;Create a 43 by 43 circle (unlike the Rectangle Tool, you can't specify the size of a circle with the Circle Tool selected. If you want to do this, you'll need to use the Selection Tool). Set a red-orange to yellow-orange radial gradient on the object and no stroke.&lt;/p&gt;

&lt;p&gt;Using the Gradient Tool, drag the center control point of the gradient to the bottom-right corner of the circle's bounding box, the endpoint of the horizontal stem to the bottom-left corner and the vertical endpoint to the top-right corner.&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvT_glMbz4I/AAAAAAAAAfY/y9d6MF-D1Dg/representative-element.png?imgmax=800" alt="representative-element.png" border="0" width="369" height="277" /&gt;

&lt;p&gt;With the circle selected, use the menu item Filters&amp;rarr;ABCs&amp;rarr;Diffuse Light. Then use the Filter Editor to set the Gaussian Blur effect of this filter to a Standard Deviation of 1.0. Then apply a drop shadow to the circle.&lt;/p&gt;

&lt;p&gt;Finally, position everything together and the icon is complete.&lt;/p&gt;

&lt;h4&gt;Icon 5: A circular Mac icon&lt;/h4&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvUaRmY_4LI/AAAAAAAAAgE/xlc_g2hon1A/icon5.png?imgmax=800" alt="icon5.png" border="0" width="164" height="164" style="float:right;padding-top:20px;padding-left:20px;padding-bottom:20px;"/&gt;

&lt;h5&gt;Goals in this section&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;See the common components of a Mac "appliance" application icon&lt;/li&gt;
&lt;li&gt;Apply effects to a path to make the boundary shape more interesting and more distinct from the background&lt;/li&gt;
&lt;li&gt;Create a texture using an effect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A circular icon is constructed in the same way as a rectangular backed icon. The only significant differences are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;gradients tend to be various kinds of radial gradient to give a convex feel to the round shape&lt;/li&gt;
&lt;li&gt;the overlayed element will be more centered so it helps if it is less solid (thinner and lighter)&lt;/li&gt;&lt;/ul&gt;

&lt;h5&gt;Compose a round icon&lt;/h5&gt;

&lt;p&gt;Since you've seen how to put together basic shapes and radial fills before, I'll just show you the components I used to create this icon as a graphic:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvUBJ2fKIkI/AAAAAAAAAfg/KbRqImnvXWg/round-icon-components.png?imgmax=800" alt="round-icon-components.png" border="0" width="550" height="133" /&gt;

&lt;p&gt;Notice how bright the elements all are: Mac icons are normally quite bright &amp;mdash; you want to avoid a "muddy" effect with too many dark colors.&lt;/p&gt;

&lt;p&gt;When composing elements, if one of them is at the wrong depth (overlaps other objects wrong) you can change the depth by selecting the object and using the Page Up/Page Down keys (or by using the "Object"&amp;rarr;"Raise"/"Lower" menu items).&lt;/p&gt;

&lt;h5&gt;Make the checkmark look interesting&lt;/h5&gt;

&lt;p&gt;The checkmark must stand alone in this icon, which means that it should have a few special effects applied to it so that it doesn't look sterile and boring. I applied the following effects to the checkmark:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Filters&amp;rarr;Non-realistic 3D shaders&amp;rarr;Comics&lt;/li&gt;
&lt;li&gt;Filters&amp;rarr;Shadows and Glows&amp;rarr;Inner Glow. For this filter, I changed the Flood color to a medium blue and reduced the Gaussian Blur (now the second blur in the Effects list for this object after the Comics blur from the previous effect) to a Standard Deviation of 1.0.&lt;/li&gt;
&lt;li&gt;A drop shadow.&lt;/li&gt;
&lt;/ol&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvUBnbY9_VI/AAAAAAAAAfk/Uu_3c10xwcc/checkmark-with-effects.png?imgmax=800" alt="checkmark-with-effects.png" border="0" width="146" height="165" /&gt;

&lt;p&gt;To texture the circle, I used the RGBA=(176,112,42,140) circle (middle element shown above) and applied a Filters&amp;rarr;Image effects, transparent&amp;rarr;Marbled ink effect. This gives a slightly moon cratered look that matches the somewhat planetoid shape of the object.&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvUCNKDO7UI/AAAAAAAAAfo/LWBmMzSEkVM/textured-circle.png?imgmax=800" alt="textured-circle.png" border="0" width="212" height="228" /&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can &lt;a href="http://projectswithlove.com/projects/cocoawithlove-inkscape-icons-part1.svg"&gt;download an Inkscape SVG file containing all the icons and their compositions&lt;/a&gt; (482kB).&lt;/blockquote&gt;

&lt;p&gt;This two part series has been outside the normal domain of programming information that I provide. However, applications programmers will regularly find themselves needing to create, edit or adjust artwork-related assets in their applications. I hope I've given some useful tips on the way artwork assets are composed and ways you can make your artwork look good, even if it is very simple.&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvAqo04PsPI/AAAAAAAAAeg/d5Pvuu0d24I/all-icons.png?imgmax=800" alt="all-icons.png" border="0" width="550" height="111" /&gt;

&lt;p&gt;With iPhone or Mac icons, they are typically composed from the same elements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A background gradient (or two).&lt;/li&gt;
&lt;li&gt;A texture or additional effect.&lt;/li&gt;
&lt;li&gt;A gloss or lighting highlight.&lt;/li&gt;
&lt;li&gt;A foreground element or symbol representing your application which, after the other elements are applied, need only be very simple.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With gradients and effects, it is helpful to use a few so that your icon seems rich on close inspection but to keep each one very subtle since they shouldn't distract or make the icon harder to perceive (in a quick glance, the user shouldn't even see the effects you've added).&lt;/p&gt;

&lt;p&gt;Icons do not need to be complex; the most professional icons are often very basic. Lack of artistic skill need not be a hinderance if you keep it simple.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-5498576471595968227?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/bhpnXirsksY" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/5498576471595968227?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/5498576471595968227?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/bhpnXirsksY/creating-iphone-and-mac-icons-using_06.html" title="Creating iPhone and Mac icons using Inkscape (Part 2 of 2)" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/11/creating-iphone-and-mac-icons-using_06.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MNSXY8fip7ImA9WxNaEko.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-8239862947234112962</id><published>2009-11-03T01:17:00.001-08:00</published><updated>2009-11-26T13:38:18.876-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-26T13:38:18.876-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="graphics" /><title>Creating iPhone and Mac icons using Inkscape (Part 1 of 2)</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In this two part series, I'll give a beginner's guide to creating iPhone and Mac application icons using Inkscape &amp;mdash; a free, vector illustration program. In this first part, I'll talk about the common styles and traits of icons on the Mac and iPhone and give a step-by-step guide to creating the first iPhone icon in Inkscape.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Introduction&lt;/h4&gt;

&lt;p&gt;This series will cover the creation of the following different icons:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvAqo04PsPI/AAAAAAAAAeg/d5Pvuu0d24I/all-icons.png?imgmax=800" alt="all-icons.png" border="0" width="550" height="111" /&gt;

&lt;p&gt;Only the first icon will be created in this part. The remaining four will be covered in the second part.&lt;/p&gt;

&lt;p&gt;It may seem strange to be covering icon creation in a Cocoa programming blog but the icon is an important part of an application and Cocoa is primarily an application programming environment. While larger development teams have dedicated graphic artists to create icons and other artwork assets, the reality is that on smaller teams or on solo projects, a programmer may need to create icons themselves.&lt;/p&gt;

&lt;p&gt;The goal of this series is to show non-graphics professionals how to create graphics of an acceptable level for their applications that follow the established visual trends for iPhone and Mac apps.&lt;/p&gt;

&lt;h4&gt;A vector approach&lt;/h4&gt;

&lt;p&gt;This post is partly a response to &lt;a href="http://elitebydesign.com/design-the-itunes-icon-for-the-iphone-and-ipod-touch/"&gt;Elite By Design's "Design The iTunes Icon For The iPhone And iPod Touch"&lt;/a&gt; which produced an iTunes-style icon at 125x125 pixels in Photoshop.&lt;/p&gt;

&lt;p&gt;I wanted to show an alternative approach to the one suggested in that article. This alternative approach has the following advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Entirely vector artwork, so it will scale from 57x57 pixels up to 512x512 pixels as required for App Store submissions.&lt;/li&gt;
&lt;li&gt;Rounded corners and gloss are applied to a separate clone of the base artwork so the submission to Apple can be non-prerendered if you choose.&lt;/li&gt;
&lt;li&gt;Created using free software as non-professional artists don't always have access to Photoshop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to detailing iPhone icon creation, the second part will also cover basic Mac icon design.&lt;/p&gt;

&lt;h4&gt;Established styles&lt;/h4&gt;

&lt;p&gt;I continue to be surprised when I look at screenshots of the Windows 7 taskbar.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Su2-d_KQikI/AAAAAAAAAbw/wtr_tUW7Me8/window7taskbar.png?imgmax=800" alt="window7taskbar.png" border="0" width="250" height="40" /&gt;

&lt;p&gt;These are the first four icons that a Windows 7 user sees and they are the strangest collection of graphics I've ever seen. They share no obvious visual style; they are all drawn with different perspective, they all have different weights, some are glossy while others are matte, some have line edges while others are self-edged (no lines) and they don't share a color palette.&lt;/p&gt;

&lt;h5&gt;Icon styles on the Mac&lt;/h5&gt;

&lt;p&gt;By contrast, icons on the Mac tend to have more in common:&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Su5HiRMhRkI/AAAAAAAAAb8/LrCUmVxpV8I/dock-icons.png?imgmax=800" alt="dock-icons.png" border="0" width="521" height="78" /&gt;

&lt;p&gt;Ignoring the "Finder" icon (which is actually the "Mac OS" icon and predates Mac OS X by about 5 years), these icons come in three distinct styles:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Document applications (rectangular background angled 5-10&amp;deg; left).&lt;/li&gt;
&lt;li&gt;Appliance applications (round &amp;mdash; or at least non-rectangular &amp;mdash; background).&lt;/li&gt;
&lt;li&gt;Utilities (orthogonal rectangular background).&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Originally, Apple had the guideline that utilities should look like they were "items sitting on a shelf" but only the disk utitilies still follow that guideline.&lt;/p&gt;

&lt;p&gt;In addition to these three categories, the icons tend to:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Have approximately the same weight (fill roughly the same amount of their visual area).&lt;/li&gt;
&lt;li&gt;Use soft gradients, sometimes (but not always) with a light gloss or highlight.&lt;/li&gt;
&lt;li&gt;Use a generally bright but slightly desaturated palette of grays, azure blues, desaturated reds and sandy yellows (utility apps tend to use more blacks and darker colors).&lt;/li&gt;
&lt;li&gt;Indicate their function or concept with an overlayed or nested element.&lt;/li&gt;
&lt;li&gt;Are self-edged and have almost no internal lines (the outline of the icon is sometimes edged for contrast)&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Of course, none of these are immutable but following them will make it easier to create a simple icon that looks like it belongs on the Mac.&lt;/p&gt;

&lt;h5&gt;Icon styles on the iPhone&lt;/h5&gt;

&lt;p&gt;The iPhone has a style that is distinct from the Mac:&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Su5SKqL8VXI/AAAAAAAAAcI/gtN6HQAx5sI/iphone-home-screen.png?imgmax=800" alt="iphone-home-screen.png" border="0" width="240" height="360" /&gt;

&lt;p&gt;Aside from the obvious round cornered background and top-down gloss effect, iPhone icons tend to use:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Strongly saturated colors&lt;/li&gt;
&lt;li&gt;A bright gradient or colorburst in the background&lt;/li&gt;
&lt;li&gt;White silhouetted representative elements over the background&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;There is certainly variation and some icons that follow their own rules entirely (the "Notes" and "App Store" icons have little in common other than the rounded corners) but the easiest path to creating an icon that looks like it belongs on the iPhone is to incorporate these elements.&lt;/p&gt;

&lt;h4&gt;Inkscape&lt;/h4&gt;

&lt;p&gt;The tool that I will use to create the icons is Inkscape. Inkscape is a GPL-licensed SVG-based vector illustration program that you can download from &lt;a href="http://www.inkscape.org/"&gt;inkscape.org&lt;/a&gt;. It is available in a Universal binary for Mac OS X 10.3.9 and newer.&lt;/p&gt;

&lt;a href="http://inkscape.org"&gt;&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Su_OR85EEjI/AAAAAAAAAdY/_-UowpH1Eo0/inkscape.png?imgmax=800" alt="inkscape.png" border="0" width="208" height="241" /&gt;&lt;/a&gt;

&lt;p style="text-align:center;"&gt;&lt;em&gt;A nice multi-purpose icon but clearly not designed with "standard Mac app" as its primary goal.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You will need X11 installed and pre-Snow Leopard users will need an updated version of X11 (download new versions from here: &lt;a href="http://xquartz.macosforge.org/"&gt;http://xquartz.macosforge.org/&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Yes, Inkscape is an X11 program, which means that Open/Save dialogs are non-standard, windows may not come to the front when you expect them too and keyboard shortcuts are all Control-X instead of Command-X. Despite this, Inkscape is generally a good program &amp;mdash; certainly far better than most X11 applications on the Mac.&lt;/p&gt;

&lt;p&gt;If you prefer a different illustration program, most of the techniques in this guide will apply. The Filter Effects and the Path Effects are probably the points that will be most different but I'm sure you can find alternatives.&lt;/p&gt;

&lt;h4&gt;Page area&lt;/h4&gt;

&lt;p&gt;Let's start with a blank document in Inkscape.&lt;/p&gt;

&lt;p&gt;A new document will appear when you start Inkscape or you can create a new document from the "File"&amp;rarr;"New"&amp;rarr;"Default" menu.&lt;/p&gt;

&lt;p&gt;Go to the "File"&amp;rarr;"Document Properties". Set the Default Units to "px" and the custom document size to 57 by 57.&lt;/p&gt;

&lt;p&gt;The reason why we set the units and use the actual pixel sizes in a vector program is this will let us align points to whole value boundaries and avoid unnecessary anti-aliasing. For example, drawing a shape with its edge at Y=0.5 will cause the actual shape border to anti-alias across two different pixels when we render at 57x57 pixels but if we set the shape border's Y coordinates to 1.0, it won't have this problem.&lt;/p&gt;

&lt;p&gt;The page area will now look tiny in the window. You can zoom in using the middle mouse button (click and drag with the middle mouse button to pan) or the "+" key. Alternately, you can zoom the document area to fill the window by pressing the "5" key.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Zooming&lt;/strong&gt;: you will need to be comfortable with zooming in the program. The "+" and "-" keys will zoom in and out at any time. The 3 key will zoom to the selection and 4 will show all drawn elements. Clicking and dragging the middle mouse button will pan the document, clicking the middle mouse button will zoom and shift-middle mouse will zoom out.&lt;/blockquote&gt;

&lt;h4&gt;Creating the glossy round rectangle&lt;/h4&gt;

&lt;p&gt;The Tool Area is the column of buttons down the left side of the window. The 5th tool from the top is the rectangle tool.&lt;/p&gt;

&lt;h5&gt;Red round rectangle&lt;/h5&gt;

&lt;p&gt;Using the rectangle tool, drag out a rectangle to fill the document area.&lt;/p&gt;

&lt;p&gt;Open the Fill and Stroke palette (menu item "Object"&amp;rarr;"Fill and Stroke" or Control-Shift-F). With the rectangle we created selected in the window, select the Stroke tab of the Fill and Stroke Palette. Make certain there is no stroke (the "X" icon should be selected). Select the Fill tab of the palette. Set a solid color fill (the solid square icon) and use the sliders to set a bright red fill (this is just so that we can see the shape easily).&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/Su_JJ2MFq9I/AAAAAAAAAdQ/RAsa5hewfKM/fill-and-stroke-palette.png?imgmax=800" alt="fill-and-stroke-palette.png" border="0" width="450" height="287" /&gt;

&lt;blockquote&gt;&lt;strong&gt;Quick colors&lt;/strong&gt;: you can also set solid fill and stroke colors on the selected object by left clicking (fill) or shift-left-clicking (stroke) a swatch at the bottom of the window.&lt;/blockquote&gt;

&lt;p&gt;We now need to edit the rectangle properties. Using the rectangle tool again, click the rectangle to select it (if it isn't already selected). In rectangle edit mode, a toolbar will appear at the top of the window labelled "Change" with coordinates "W", "H", "Rx" and "Ry". Set the "W" and "H" to 57 &amp;mdash; this will make the rectangle exactly 57 pixels wide and high (if the rectangle auto-locked to the edges of the document, these values may already be set). Set the "Rx" and "Ry" to 10 &amp;mdash; this will set the corner radii to 10 (a round rect).&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Su_Jn4WeKnI/AAAAAAAAAdU/FWj-ddbVaCc/round-rect.png?imgmax=800" alt="round-rect.png" border="0" width="455" height="380" /&gt;

&lt;blockquote&gt;&lt;strong&gt;Numerical accuracy&lt;/strong&gt;: I'm going to quote a lot of coordinates and color values in this post but this is only so I can communicate what I'm doing. Most of the time, you do not need to be pixel accurate and can do things more approximately if you prefer.&lt;/blockquote&gt;

&lt;p&gt;Using the selection tool (the first tool in the Tool Area) select the rectangle. The object's "X" and "Y" coordinates will appear in the toolbar at the top. Set these to zero. The rectangle is now exactly the size of the document with round corners.&lt;/p&gt;

&lt;h5&gt;The gloss round rectangle&lt;/h5&gt;

&lt;p&gt;Copy the red round rectangle object (select it and press Control-C) and paste it (Control-V) somewhere else (when pasted, the object will be centered where the mouse is, so place the mouse over a different part of the document).&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Copy and Paste bug&lt;/strong&gt;: if the Copy and Paste fails (you get a bitmap instead of a proper editable object or nothing seems to happen), then you may be seeing a bug in Inkscape due to recent X11 changes. To work around this bug, go to the X11 preferences and on the Pasteboard tab, disable "Update Pasteboard when CLIPBOARD changes". Alternatively, you can use "Edit"&amp;rarr;"Duplicate" to duplicate without copying.&lt;/blockquote&gt;

&lt;p&gt;With the copy selected, go to the Fill tab of the Fill and Stroke palette. Set a radial fill for the object (4th icon from the left at the top). If you've set the red color, then the radial gradient will initially look like a red dot fading outwards.&lt;/p&gt;

&lt;p&gt;Click the "Edit" button in the Fill tab to edit the gradient. In the "Gradient Editor" that appears, the popup menu at the top will contain two items (the opaque red color and the fully transparent red color). Hit the "Add Stop" button twice to add two extra items in the gradient.&lt;/p&gt;

&lt;p&gt;Edit the topmost item in the list of colors (the opaque red color) and set it to white with an alpha value of 86. Set the second item to white with an alpha of 75. Set the third to black with an alpha of 60. Set the final item to white aith an alpha of 0.&lt;/p&gt;

&lt;p&gt;You also need to set the offset of the two middle colors. The black color should have an offset of 0.63. The white color should have an offset of 0.62.&lt;/p&gt;

&lt;p&gt;This round rectangle should now look like a faint gray donut. Select it and set its "X" and "Y" coordinates to (0,0) (so that it perfectly overlaps the original red round rectangle).&lt;/p&gt;

&lt;p&gt;With the faint gray donut selected, choose the Gradient Tool (second last in the Tool Area &amp;mdash; if your vertical screen resolution isn't very high, you may need to select the Gradient Tool from the popup menu at the bottom of the Tool Area). An "L" shape of control points should appear over the donut.&lt;/p&gt;

&lt;p&gt;Drag the control point that appears in the middle of the donut to the middle of the top edge of the round rect (it should lock onto the point with the text "Handle to bounding box").&lt;/p&gt;

&lt;p&gt;Drag the round control point at the end of the horizontal arm of the "L" to X=-50. You can see the "X" value of the cursor at the bottom right of the window. Hold down the "Control" key while doing this to ensure that the "Y" value remains the same. Similarly, drag the round control point at the end of the vertical arm to Y=12.&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Su_OtaO6UNI/AAAAAAAAAdc/9XU4VRXloOI/gradient-control-points.png?imgmax=800" alt="gradient-control-points.png" border="0" width="500" height="270" /&gt;

&lt;p&gt;On the Stroke tab of the Fill and Stroke palette, set a linear gradient stroke (third icon from the left at the top) for the gloss object. On the Stroke Style tab, set the line width to 1.0 px.&lt;/p&gt;

&lt;p&gt;On the Stroke tab, edit the gradient. Set the start color to white and the end color to RGBA=(255,255,255,0). Using the Gradient Tool, select the gloss object. There should now be an extra set of control points in a horizontal line across the middle of the object corresponding to the stroke's gradient. Drag the start point  of this line (square control point) to the top right corner of the object and the end point of the line (circular control point) to a position three quarters the way up the right-hand side of the object.&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvAqCHnzXzI/AAAAAAAAAeY/OyHPG5n9c04/stroke-gradient.png?imgmax=800" alt="stroke-gradient.png" border="0" width="550" height="360" /&gt;

&lt;p&gt;Since the stroke added to the gloss object changed the size of the object, you will need to re-set the size of the gloss object to 57x57 at X,Y=(0,0).&lt;/p&gt;

&lt;p&gt;You should now have a glossy red round rectangle in the style of an iPhone icon. If you know what you're doing in Inkscape, you can move these objects to another layer and hide them now however, it's probably easiest just to save this document and copy these objects when they are needed later.&lt;/p&gt;

&lt;h4&gt;The first iPhone icon&lt;/h4&gt;

&lt;h5&gt;Blue-green background&lt;/h5&gt;

&lt;p&gt;Create a 57 by 57 rectangle at X,Y=(0,0) again, using the same approach as the red rectangle from the previous section but leave the corners square (you may need to explicitly set Rx and Ry to zero since it may remember the radius from before).&lt;/p&gt;

&lt;p&gt;Set the fill of this rectangle to a linear gradient (third icon from the left at the top of the Fill tab in the Fill and Stroke palette). Edit the gradient and set the start point to RGBA=(15,112,126,255) and the end point to RGBA=(0,0,53,255).&lt;/p&gt;

&lt;p&gt;Using the Gradient Tool from the Tool Area, select the rectangle and drag the gradient starting point (the square control point) to the center of the bottom edge of the rectangle. Drag the gradient end point (the round control point) to the center of the top edge of the rectangle.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Su_Z-LnJJJI/AAAAAAAAAdw/O_6pFldbppw/blue-green-gradient.png?imgmax=800" alt="blue-green-gradient.png" border="0" width="550" height="407" /&gt;

&lt;blockquote&gt;&lt;strong&gt;Gradient colors&lt;/strong&gt;: almost every gradient you use should involve a hue shift. When you want an actual 3D or lighting effect, you can also apply a luminance shift. The gradient here shifts from blue into the green direction as it lightens (a common choice). The other most common gradient would probably be from a darker red or orange towards a lighter yellowy orange. Hues on the green side of yellow or purple hues are rarely ever used.&lt;/blockquote&gt;

&lt;h5&gt;Starburst object&lt;/h5&gt;

&lt;p&gt;Now, using the Stars and Polygons tool from the Tool Area (8th from the top) and drag out a shape (it will probably appear as a 5 point star &amp;mdash; if it isn't a star, click the star icon in the top toolbar). With the Stars and Polygons tool and the object still selected, you should be able to edit the properties of the star. Set the number of corners to 350, the spoke ratio to 0.3 and the Randomized property to 0.015. Choose the Select and Transform tool (first tool in the Tool Area) and select the star. You can now set the width and height both to 87 and the X,Y to (-15,-15).&lt;/p&gt;

&lt;p&gt;In the Fill and Stoke palette, set the opacity of the star to 50%.&lt;/p&gt;

&lt;p&gt;Then, set a radial fill on the star from a start color of RGBA=(255,255,255,0) to an end color of RGBA=(0,235,255,255). This radial gradient fades out in the middle which will help the checkbox stand out from the background more.&lt;/p&gt;

&lt;h5&gt;A blur effect on the starburst&lt;/h5&gt;

&lt;p&gt;With the star object still selected, select the menu item "Filters"&amp;rarr;"ABCs"&amp;rarr;"Simple Blur". Then select the "Filters"&amp;rarr;"Filter Editor..." menu item. This will display the Filter Editor palette.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Space limitations&lt;/strong&gt;: If the Fill and Stroke Palette is still showing when the Filter Editor appears, you'll notice that they don't fit well together down the right margin. I recommend you either close the Fill and Stroke Editor or drag the Filter Editor off into its own window.&lt;/blockquote&gt;

&lt;p&gt;There should be one filter listed in the list of filters &amp;mdash; this is the filter you just created. When you select the filter in the list, the Effect "Gaussian Blur" will appear in the Effect column at the right. Select the Gaussian Blur and the "Effect Parameters" tab will appear at the bottom. Set the "Standard Deviation" to 0.25.&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Su_aO4pc1LI/AAAAAAAAAd0/FucG8cgzj0Y/starburst.png?imgmax=800" alt="starburst.png" border="0" width="550" height="371" /&gt;

&lt;p&gt;You can also apply "Blur" using the Fill and Stroke palette. The blur radius at the bottom of this palette is 2.74 times the Standard Deviation applied here (no, I'm not really sure why the difference is 2.74 times).&lt;/p&gt;

&lt;h5&gt;The checkbox and checkmark objects&lt;/h5&gt;

&lt;p&gt;Now create a 29x29 round rectangle with corner radius 4 at X,Y=(14,14). This is the checkbox. This time, set no fill (the "X" icon on the Fill tab of the Fill and Stroke palette) and set a plain stroke (second icon from the left at the top of the Stroke tab) with a white color. On the "Stroke Style" tab, set the width to 3.0 "px". While here, set the "Cap" to round. It won't matter as much for this object, but we're just about to draw a line and we want it to have round endcaps.&lt;/p&gt;

&lt;p&gt;Select the Bezier Line tool (11th icon down in the Tool Area). Click the mouse and release to create points at X,Y = (19.5,30), (28.5,20) and (47,48). Press the return key when done to finish the path. This is the checkmark. Now select the Node Tool (second icon from the top of the Tool Area) and select the checkmark. Click and hold the mouse in the middle of each line segment and drag up slightly to give the lines a slight curve. You can use the control points to tweak the effect if you're not happy.&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Su_acYjqXsI/AAAAAAAAAd4/TNYVoVawgcc/node-tool.png?imgmax=800" alt="node-tool.png" border="0" width="295" height="292" /&gt;

&lt;h5&gt;Bevel effect and shadow&lt;/h5&gt;

&lt;p&gt;Select the checkmark and the checkbox. From the Filters menu select "Bevels"&amp;rarr;"Ridged Border". Then from the Filters menu select "Shadows and Glows"&amp;rarr;"Drop Shadow", set the blur to 2.0, the opacity to 35%, the offset to (3,3), hit the "Apply" button and close the Drop shadow dialog.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Speed tip&lt;/strong&gt;: when zoomed in on objects using effects, the rendering can get slow. To disable effects or to drop entirely into wireframe mode, choose "No Filters" or "Outline" from the "View"&amp;rarr;"Display Mode" menu or press Control-Keypad5. The "Ridged border" effect is especially slow in the current version of Inkscape &amp;mdash; I recommend zooming out before you apply it and turning effects off before you zoom in close.&lt;/blockquote&gt;

&lt;p&gt;If you want to fully integrate the checkmark and the checkbox, you can convert the checkbox object to a path, the checkmark stroke to a path and then create a union of the two. I'll leave that to you if you're interested.&lt;/p&gt;

&lt;h5&gt;Apply the gloss effect and round corners&lt;/h5&gt;

&lt;p&gt;Select the green gradient background, the starburst, the checkbox and the checkmark and group them all together (Control-G or menu "Object"&amp;rarr;"Group"). This will let you select them all in one go (ungroup with Control-Shift-G or double-click the group to select objects within the group without ungrouping).&lt;/p&gt;

&lt;p&gt;With the group selected, from the Edit menu select "Clone"&amp;rarr;"Create Clone". This will create a copy that continues to update when the original updates. Move the clone to X,Y=(-115.7,-15.7) (this coordinate include extra padding of approximately 2.74 times the starburst's blur standard deviation of 0.25 which is the amount that a blur will expand an object's boundary).&lt;/p&gt;

&lt;p&gt;Now we need the red glossy round rectangle. If you saved them in a different document, copy them into this document now. Select the red background and gloss (drag a rectangle around both using the Selection Tool) and set the X,Y coordinates of the two of them to (-100,0). This may make the two objects hidden behind the cloned group objects so press the "Home" key (or select Raise to Top from the Object menu).&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/Sw71PAOnchI/AAAAAAAAAgc/f5mTDGB9_jE/redrectclone.png?imgmax=800" alt="redrectclone.png" border="0" width="454" height="216" /&gt;

&lt;p&gt;Drag the gloss and the red rectangle off of the objects they are covering (it doesn't matter where you put them). Select the cloned group and the red round rectangle but not the gloss gradient. Undo the two object moves. This should leave the cloned objects and the red round rectangle selected but all of the objects on top of each other. From the Object menu, select "Clip"&amp;rarr;"Set". This should clip the cloned group to the boundary of the red round rectangle, and make the red round rectangle disappear.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Clipping&lt;/strong&gt;: when clipping in Inkscape, the topmost object is always used as the clipping boundary and all other selected objects are clipped to its boundary.&lt;/blockquote&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvAqLLOREPI/AAAAAAAAAec/p4AYpJ_w6wU/side-by-side.png?imgmax=800" alt="side-by-side.png" border="0" width="444" height="223" /&gt;

&lt;h4&gt;Export the bitmap&lt;/h4&gt;

&lt;p&gt;Congratulations, your iPhone icon is complete.&lt;/p&gt;

&lt;p&gt;You can export the prerendered (cloned, glossed and rounded) version to a PNG by selecting the gloss gradient that's over the clipped shape and selecting "Export Bitmap" from the "File" menu. Make sure that "Selection" is highlighted in the window that appears and set the width and height of the exported image to whatever size you want. Use the Browse button to select a location then hit the export button.&lt;/p&gt;

&lt;p&gt;If you want to send the non-prerendered version to Apple, then select the uncloned group and export from that. 57x57 for the application icon and 512x512 for the high resolution version in your App Store submission.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Resampling&lt;/strong&gt;: You may get a better effect on the small icon if you export at a larger size and use another program (Preview, GIMP, etc) to scale it down. This may give better anti-aliasing performance &amp;mdash; particularly if your resizing program uses Lanczos resampling.&lt;/blockquote&gt;

&lt;p&gt;If you'd like your icon as a PDF, SVG or a number of other vector graphics types, you can choose "Save As..." and save to the format of your choice.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can &lt;a href="http://projectswithlove.com/projects/cocoawithlove-inkscape-icons-part1.svg"&gt;download an Inkscape SVG file containing the final icon&lt;/a&gt; (122kb). Note: Safari and other programs will open SVG files but the effects (shadows, blurs, etc) will only appear if the SVG is opened in Inkscape.&lt;/blockquote&gt;

&lt;p&gt;In the second part, I will go through the steps for other icons, showing different stylistic options and explaining more of the effects and graphical elements you can use to create your icons. I'll look closer at filter effects in Inkscape, creating more sophisticated line paths, using gradients in multiple directions to achieve softer effects and creating simple textures to fill blank areas.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-8239862947234112962?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/tOR13_XXjyQ" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8239862947234112962?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8239862947234112962?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/tOR13_XXjyQ/creating-iphone-and-mac-icons-using.html" title="Creating iPhone and Mac icons using Inkscape (Part 1 of 2)" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/11/creating-iphone-and-mac-icons-using.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQBQ3o7fCp7ImA9WxNVFU4.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-7079014197513352171</id><published>2009-10-25T04:26:00.001-07:00</published><updated>2009-10-25T21:12:32.404-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-25T21:12:32.404-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="fun hacks" /><title>Memory and thread-safe custom property methods</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Objective-2.0 property methods are a nice convenience but if you need to override a property implementation &amp;mdash; particularly an atomic, retained or copied object setter property &amp;mdash; there are some potential bugs you can create if you don't follow the rules carefully. I'll show you the pitfalls and the correct way to implement a property accessor. I'll also show a way to directly invoke hidden runtime functions to let Objective-C perform atomic getting and setting safely for you.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Custom getter and setter methods for implicitly atomic types&lt;/h4&gt;

&lt;p&gt;For implicitly atomic types or for types where memory management doesn't apply, custom getter and setter methods in Objective-C are easy. These "easy" situations include:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Basic value types (&lt;code&gt;char&lt;/code&gt;, &lt;code&gt;short&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;long&lt;/code&gt;, &lt;code&gt;double&lt;/code&gt;, etc).&lt;/li&gt;
&lt;li&gt;Objective-C objects in a garbage collected environment&lt;/li&gt;
&lt;li&gt;Assigned (non-retained) pointers&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;For these types, it is pretty hard to get a custom getter or setter method wrong. For the following property declaration:&lt;/p&gt;

&lt;pre&gt;@property SomeAtomicType somePropertyVariable;&lt;/pre&gt;

&lt;p&gt;the custom getter and setter simply look like this:&lt;/p&gt;

&lt;pre&gt;- (SomeAtomicType)somePropertyVariable
{
    return somePropertyVariable;
}
- (void)setSomePropertyVariable:(SomeAtomicType)aValue
{
    somePropertyVariable = aValue;
}&lt;/pre&gt;

&lt;h4&gt;Common mistakes in accessor methods for non-atomic types&lt;/h4&gt;

&lt;p&gt;Non-atomic types require greater care. These types include:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Objective-C objects in a manually managed memory environment&lt;/li&gt;
&lt;li&gt;&lt;code&gt;struct&lt;/code&gt;s and other compound types&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Given how simple custom getter and setter methods are for atomic types, it is easy to be complacent about implementing methods for these types. However, following the wrong approach can lead to memory crash bugs and lack of proper thread safety.&lt;/p&gt;

&lt;p&gt;To illustrate how simple it can be to introduce bugs while implementing a custom setter method, consider the following declared property:&lt;/p&gt;

&lt;pre&gt;@property NSString (copy) someString;&lt;/pre&gt;

&lt;p&gt;A hasty implementation of the setter might be:&lt;/p&gt;

&lt;pre&gt;- (void)setSomeString:(NSString *)aString
{
    [someString release];
    someString = [aString copy];
}&lt;/pre&gt;

&lt;p&gt;This implementation actually contains two bugs:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;&lt;strong&gt;This method is not atomic.&lt;/strong&gt;&lt;br/&gt;The &lt;code&gt;someString&lt;/code&gt; object changes twice: once on &lt;code&gt;release&lt;/code&gt; and again when it is assigned the copied object's address. This method is &lt;em&gt;not&lt;/em&gt; atomic and therefore violates the declaration (which omits the &lt;code&gt;nonatomic&lt;/code&gt; keyword and therefore requires atomicity).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The assignment contains a potential memory deallocation bug.&lt;/strong&gt;&lt;br/&gt;If &lt;code&gt;someString&lt;/code&gt; is ever assigned its own value, it will &lt;code&gt;release&lt;/code&gt; it before &lt;code&gt;copy&lt;/code&gt;ing it, causing potential use of a &lt;code&gt;release&lt;/code&gt;d variable. The code: &lt;code&gt;self.someString = someString;&lt;/code&gt; is an example of this potential issue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Don't feel too bad if you've ever made these mistakes. I spent some time looking at &lt;a href="http://clang.llvm.org/"&gt;clang's&lt;/a&gt; synthesized method implementations when I was researching this post and I noticed that &lt;a href="http://llvm.org/svn/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp"&gt;they've forgotten to handle struct accessor methods in an atomic manner&lt;/a&gt; when required.&lt;/p&gt;

&lt;h4&gt;Safe implementations of custom accessor methods for non-atomic types&lt;/h4&gt;

&lt;p&gt;To address this second issue, &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html"&gt;Apple's Declared Properties documentation&lt;/a&gt; suggests that your setter methods should look like this:&lt;/p&gt;

&lt;pre&gt;- (void)setSomeString:(NSString *)aString
{
    if (someString != aString)
    {
        [someString release];
        someString = [aString copy];
    }
}&lt;/pre&gt;

&lt;p&gt;This only fixes the memory issue, it doesn't fix the atomicity issue. To handle that, the only simple solution is to used a &lt;code&gt;@synchronized&lt;/code&gt; section:&lt;/p&gt;

&lt;pre&gt;- (void)setSomeString:(NSString *)aString
{
    @synchronized(self)
    {
        if (someString != aString)
        {
            [someString release];
            someString = [aString copy];
        }
    }
}&lt;/pre&gt;

&lt;p&gt;This approach will also work for &lt;code&gt;retain&lt;/code&gt; properties as well (simply replace the &lt;code&gt;copy&lt;/code&gt; method with a &lt;code&gt;retain&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To maintain atomicity, you also need a &lt;code&gt;retain/autorelease&lt;/code&gt; pattern and lock on any getter methods too:&lt;/p&gt;

&lt;pre&gt;- (NSString *)someString
{
    @synchronized(self)
    {
        id result = [someString retain];
    }
    return [result autorelease];
}&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;@synchronized&lt;/code&gt; section is only required around the &lt;code&gt;retain&lt;/code&gt; since that will prevent a setter releasing the value before we can return it (the &lt;code&gt;autorelease&lt;/code&gt; is then safely done outside the section).&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;struct&lt;/code&gt; and other compound data types, we don't need to &lt;code&gt;retain&lt;/code&gt; or &lt;code&gt;copy&lt;/code&gt;, so only the &lt;code&gt;@synchronized&lt;/code&gt; section is required:&lt;/p&gt;

&lt;pre&gt;- (NSRect)someRect
{
    @synchronized(self)
    {
        return someRect;
    }
}
- (void)setSomeRect:(NSRect)aRect
{
    @synchronized(self)
    {
        someRect = aRect;
    }
}&lt;/pre&gt;

&lt;h4&gt;A faster, shorter way to implement custom accessors&lt;/h4&gt;

&lt;p&gt;There are two negative points to the custom accessor methods listed above:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;They need to be coded exactly to avoid bugs.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;@synchronized&lt;/code&gt; section on &lt;code&gt;self&lt;/code&gt; is coarse-grained and slow.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;There is another way to implement these methods that doesn't require as much careful coding and uses much more efficient locking: use the same functions that the &lt;code&gt;synthesized&lt;/code&gt; methods use.&lt;/p&gt;

&lt;p&gt;The following functions are implemented in the Objective-C runtime:&lt;/p&gt;

&lt;pre&gt;id &lt;strong&gt;objc_getProperty&lt;/strong&gt;(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic);
void &lt;strong&gt;objc_setProperty&lt;/strong&gt;(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic,
    BOOL shouldCopy);
void &lt;strong&gt;objc_copyStruct&lt;/strong&gt;(void *dest, const void *src, ptrdiff_t size, BOOL atomic,
    BOOL hasStrong);&lt;/pre&gt;

&lt;p&gt;While these functions are implemented in the runtime, they are not declared, so if you want to use them, you must declare them yourself (the compiler will then find their definitions when you compile).&lt;/p&gt;

&lt;p&gt;These methods are much faster than using a &lt;code&gt;@synchronized&lt;/code&gt; section on the whole object because (as shown in their &lt;a href="http://www.opensource.apple.com/source/objc4/objc4-371.2/runtime/Accessors.subproj/objc-accessors.m"&gt;Apple opensource implementation&lt;/a&gt;) they use a finely grained, instance variable only spin lock for concurrent access (although the copy struct function uses two locks following an interface design mixup).&lt;/p&gt;

&lt;p&gt;When you declare these functions, you can also declare the following convenience macros:&lt;/p&gt;

&lt;pre&gt;#define &lt;strong&gt;AtomicRetainedSetToFrom&lt;/strong&gt;(dest, source) \
    objc_setProperty(self, _cmd, (ptrdiff_t)(&amp;dest) - (ptrdiff_t)(self), source, YES, NO)
#define &lt;strong&gt;AtomicCopiedSetToFrom&lt;/strong&gt;(dest, source) \
    objc_setProperty(self, _cmd, (ptrdiff_t)(&amp;dest) - (ptrdiff_t)(self), source, YES, YES)
#define &lt;strong&gt;AtomicAutoreleasedGet&lt;/strong&gt;(source) \
    objc_getProperty(self, _cmd, (ptrdiff_t)(&amp;source) - (ptrdiff_t)(self), YES)
#define &lt;strong&gt;AtomicStructToFrom&lt;/strong&gt;(dest, source) \
    objc_copyStruct(&amp;dest, &amp;source, sizeof(__typeof__(source)), YES, NO)&lt;/pre&gt;

&lt;p&gt;I like to include the "To/From" words so I can remember the ordering of the source and destination parameters. You can remove them if they bother you.&lt;/p&gt;

&lt;p&gt;With these macros, the &lt;code&gt;someString&lt;/code&gt; "copy" getter and setter methods above would become:&lt;/p&gt;

&lt;pre&gt;- (NSString *)someString
{
    return AtomicAutoreleasedGet(someString);
}
- (void)setSomeString:(NSString *)aString
{
    AtomicCopiedSetToFrom(someString, aString);
}&lt;/pre&gt;

&lt;p&gt;and the someRect accessor methods shown above would become:&lt;/p&gt;

&lt;pre&gt;- (NSRect)someRect
{
    NSRect result;
    AtomicStructToFrom(result, someRect);
    return result;
}
- (void)setSomeRect:(NSRect)aRect
{
    AtomicStructToFrom(someRect, aRect);
}&lt;/pre&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Most of the accessor methods I've shown here are atomic but in reality, most Objective-C object accessors are declared &lt;code&gt;nonatomic&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Even if your properties are declared &lt;code&gt;nonatomic&lt;/code&gt;, the memory management rules still apply. These rules are important to follow since they can lead to some very obscure and hard to track down memory bugs.&lt;/p&gt;

&lt;p&gt;The macros I've provided are all for atomic properties. For non-atomic properties the boilerplate assignment code is probably simple enough to remember. If not, you could also use a macro:&lt;/p&gt; &lt;pre&gt;#define &lt;strong&gt;NonatomicRetainedSetToFrom&lt;/strong&gt;(a, b) do{if(a!=b){[a release];a=[b retain];}}while(0)
#define &lt;strong&gt;NonatomicCopySetToFrom&lt;/strong&gt;(a, b) do{if(a!=b){[a release];a=[b copy];}}while(0)&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; following comments below, I realize I omitted to qualify the situations in which these accessors are thread-safe. Specifically:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;These setter methods are only thread-safe if the parameters passed to them are immutable. For mutable parameters, you may need to ensure thread safety between mutations on the parameter and the assignment of the property.&lt;/li&gt;
&lt;li&gt;Atomic accessors only provide thread safety to an instance variable if they are the sole way you access the instance variable. If non-property access is required, you must ensure shared thread safety between property accessor methods and the non-property access.&lt;/li&gt;
&lt;li&gt;Atomic assignment for the "implicitly atomic" types I listed does not mean that all CPUs/cores see the same thing (since each CPU/core could have its own cache of the value) &amp;mdash; it only ensures that value is wholly set without possibility of interruption. If you require all CPUs/core to be synchronized and see the same value at a given moment, then even the "implicitly atomic" types may require &lt;code&gt;volatile&lt;/code&gt; qualifiers or a &lt;code&gt;@synchronized&lt;/code&gt; section around the assignment to flush caches.&lt;/li&gt;
&lt;/ol&gt;


&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-7079014197513352171?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/dInWmVy_0Z0" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7079014197513352171?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7079014197513352171?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/dInWmVy_0Z0/memory-and-thread-safe-custom-property.html" title="Memory and thread-safe custom property methods" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/10/memory-and-thread-safe-custom-property.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8BSH49cSp7ImA9WxNWGUw.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-2347122604201755491</id><published>2009-10-18T02:12:00.001-07:00</published><updated>2009-10-18T17:40:59.069-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-18T17:40:59.069-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Snow Leopard" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Standard C" /><title>How blocks are implemented (and the consequences)</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;

&lt;p&gt;This post is a look at how clang implements blocks and how this implementation leads to a number of strange behaviors including local variables that end up global, Objective-C objects allocated on the stack instead of the heap, C variables that behave like C++ references, Objective-C objects in non-Objective-C languages, copy methods that don't copy and retain methods that don't retain.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;What blocks are to the compiler&lt;/h4&gt;

&lt;p&gt;Blocks are addressable sections of code implemented inline (inside other functions). The inline-edness can be convenient but the real reason why blocks are different to regular functions and function pointers is that they can reference local variables from the scope of the function surrounding their implementation without the invoker of the block needing to know of the surrounding scope variables' existence.&lt;/p&gt;

&lt;p&gt;A block is implemented internally using two pieces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;compiled code in the &lt;code&gt;.text&lt;/code&gt; segment of the executable&lt;/li&gt;
&lt;li&gt;a data structure that predominantly contains the values of the variables that the block uses from its surrounding scope&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The compiled code lives in its own separate location and does not actually reside inside inside the code of its surrounding scope. In implementation, the code is a function like any other. If you run:&lt;/p&gt;

&lt;pre&gt;otool -tV MyCompiledExecutable&lt;/pre&gt;

&lt;p&gt;then you'll see your blocks appearing immediately after their surrounding functions with names like &lt;code&gt;___surroundingFunction_block_invoke_21&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So it is not the code which makes blocks special, it is the separate data structure. It is this data structure that I will focus on for the remainder of this post.&lt;/p&gt;

&lt;h4&gt;The block data structure&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://clang.llvm.org/docs/BlockImplementation.txt"&gt;Clang's basic documentation on block implementations&lt;/a&gt; indicates that the data structure describing the block looks something like this:&lt;/p&gt;

&lt;pre&gt;struct Block_literal {
    void *isa;

    int flags;
    int reserved; // is actually the retain count of heap allocated blocks

    void (*invoke)(void *, ...); // a pointer to the block's compiled code

    struct Block_descriptor {
        unsigned long int reserved; // always nil
        unsigned long int size; // size of the entire Block_literal
        
        // functions used to copy and dispose of the block (if needed)
        void (*copy_helper)(void *dst, void *src);
        void (*dispose_helper)(void *src); 
    } *descriptor;

    // Here the struct contains one entry for every surrounding scope variable.
    // For non-pointers, these entries are the actual const values of the variables.
    // For pointers, there are a range of possibilities (__block pointer,
    // object pointer, weak pointer, ordinary pointer)
};&lt;/pre&gt;

&lt;p&gt;Of course, the reality is that this structure is never explicitly declared like this in clang. Clang is a compiler &amp;mdash; a code generator &amp;mdash; and the format of this structure is &lt;em&gt;generated&lt;/em&gt; programmatically from the &lt;a href="http://clang.llvm.org/doxygen/CGBlocks_8cpp-source.html#l00103"&gt;CodeGenFunction::BuildBlockLiteralTmp&lt;/a&gt; method.&lt;/p&gt;

&lt;h4&gt;Stack blocks and global blocks&lt;/h4&gt;

&lt;p&gt;Since the biggest difference between a function pointer and a block is the ability to use variables from the surrounding scope, it is interesting to look at what happens when a block does not reference anything in the surrounding scope.&lt;/p&gt;

&lt;p&gt;Normally, the &lt;code&gt;Block_literal&lt;/code&gt; data appears on the stack (like a regular &lt;code&gt;struct&lt;/code&gt; would in its surrounding function). With no references to the surrounding scope, clang configures the &lt;code&gt;Block_literal&lt;/code&gt; as a &lt;em&gt;global&lt;/em&gt; block instead. This causes the block to appear in a fixed global location instead of on the stack (the &lt;code&gt;flags&lt;/code&gt; value has the &lt;code&gt;BLOCK_IS_GLOBAL&lt;/code&gt; flag set to indicate this at runtime but it's not immediately clear to me if this is ever used).&lt;/p&gt;

&lt;p&gt;The implication of this is that global blocks are never actually copied or disposed, even if you invoke the functions to do so. This optimisation is possible because without any references to the surrounding scope, no part of the block (neither its code nor its &lt;code&gt;Block_literal&lt;/code&gt;) will ever change &amp;mdash; it becomes a shared constant value.&lt;/p&gt;

&lt;h4&gt;Blocks are always objects&lt;/h4&gt;

&lt;p&gt;If you're familiar with how Objective-C objects are declared, the &lt;code&gt;isa&lt;/code&gt; field in the &lt;code&gt;Block_literal&lt;/code&gt; above should be familiar &amp;mdash; blocks are Objective-C objects. This may not seem strange in Objective-C but the reality is that even in pure C or C++, blocks are still Objective-C objects and the runtime support for blocks handles the &lt;code&gt;retain&lt;/code&gt;/&lt;code&gt;release&lt;/code&gt;/&lt;code&gt;copy&lt;/code&gt; behaviors for the block in an Objective-C messaging manner.&lt;/p&gt;

&lt;p&gt;Clang uses the class names &lt;code&gt;_NSConcreteStackBlock&lt;/code&gt; and &lt;code&gt;_NSConcreteGlobalBlock&lt;/code&gt; to refer to the classes for block literals but in CoreFoundation projects, this will map onto &lt;code&gt;NSStackBlock&lt;/code&gt; and &lt;code&gt;NSGlobalBlock&lt;/code&gt;. If you copy an &lt;code&gt;NSStackBlock&lt;/code&gt;, it will return an &lt;code&gt;NSMallocBlock&lt;/code&gt; (indicating its changed allocation location).&lt;/p&gt;

&lt;h4&gt;Blocks are slightly weird objects&lt;/h4&gt;

&lt;p&gt;The interesting point to note about &lt;code&gt;NSStackBlock&lt;/code&gt; is that it is a stack allocated Objective-C object. If you have ever tried to allocate an Objective-C object on the stack (not as a pointer but statically allocated) you'll know that the compiler normally forbids this.&lt;/p&gt;

&lt;p&gt;The reason why blocks are placed on the stack by default is speed. In the common case where the lifetime of the block is less than that of the stack function that contains it, this is a very good optimisation.&lt;/p&gt;

&lt;p&gt;The implication of stack blocks being allocated on the stack, is that a stack block cannot simply be &lt;code&gt;retain&lt;/code&gt;ed &amp;mdash; it will become invalid once the function that contains it is popped from the stack. If you invoke &lt;code&gt;retain&lt;/code&gt; on a stack block, it will have no effect (the retain count of the block will remain at 1).&lt;/p&gt;

&lt;p&gt;For this reason, if you need to return a block from a function or method, you must &lt;code&gt;[[block copy] autorelease]&lt;/code&gt; it, not simply &lt;code&gt;[[block retain] autorelease]&lt;/code&gt; it.&lt;/p&gt;

&lt;h4&gt;__block values can move magically&lt;/h4&gt;

&lt;p&gt;Scope variables used in a block are normally passed to the block by &lt;code&gt;const&lt;/code&gt; value (the compiler won't let you change the value but even if it did, the change wouldn't affect the value of the variable outside the block).&lt;/p&gt;

&lt;p&gt;To alter this behavior, the type specifier &lt;code&gt;__block&lt;/code&gt; was added. Any variable declared &lt;code&gt;__block&lt;/code&gt; is passed by reference into the block (value on the outside will be changed after the block is invoked).&lt;/p&gt;

&lt;p&gt;In the implementation, &lt;code&gt;__block&lt;/code&gt; variables are initially allocated on the stack but if any block which references them is copied, they are moved onto the heap (&lt;code&gt;malloc&lt;/code&gt;ed). This leads to the following strange situation...&lt;/p&gt;

&lt;pre&gt;int (^function())()
{
    __block int x = 0;
    
    int (^block)() = ^{
        x += 1;
        return x;
    };
    
    NSLog(@"x's location is on the stack: %p", &amp;x);
    block = [[block copy] autorelease];
    NSLog(@"x's location is now on the heap: %p", &amp;x);
    
    return block;
}&lt;/pre&gt;

&lt;p&gt;In this example, x's address changes when the copy is invoked. This is because when we declare a &lt;code&gt;__block&lt;/code&gt; variable, a pointer to the real variable is created and any attempt to use the variable dereferences it. When &lt;code&gt;copy&lt;/code&gt; is invoked, the location pointed to by the pointer changes to the new heap location, so any use of &lt;code&gt;x&lt;/code&gt; causes a dereference to this new location.&lt;/p&gt;

&lt;p&gt;This makes &lt;code&gt;__block&lt;/code&gt; similar to to a reference parameter in C++ since C++ references are also transparently dereferenced pointers.&lt;/p&gt;

&lt;h4&gt;NSMallocBlock never actually copies&lt;/h4&gt;

&lt;p&gt;Copying a block doesn't really give you a copy of the block &amp;mdash; if the block is already an &lt;code&gt;NSMallocBlock&lt;/code&gt;, a &lt;code&gt;copy&lt;/code&gt; simply increases the retain count of the block (this retain count is an internal &lt;code&gt;reserved&lt;/code&gt; field &amp;mdash; the &lt;code&gt;retainCount&lt;/code&gt; returned from the object will remain at 1). This is perfectly appropriate since the scope of the block cannot change after it is created (therefore the block is constant) but it does mean that invoking &lt;code&gt;copy&lt;/code&gt; on a block is not the same thing as recreating it.&lt;/p&gt;

&lt;p&gt;Assume the following code is in the same program as the previous example.&lt;/p&gt;

&lt;pre&gt;int (^someBlock)() = counterBlock();
int (^someBlockCopy)() = [[someBlock copy] autorelease];
int (^anotherBlock)() = counterBlock();&lt;/pre&gt;

&lt;p&gt;The block returned from &lt;code&gt;counterBlock()&lt;/code&gt; counts the number of times that it is invoked by saving the count in the &lt;code&gt;__block&lt;/code&gt; variable &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this example though, &lt;code&gt;someBlock&lt;/code&gt; and &lt;code&gt;someBlockCopy&lt;/code&gt; share the same &lt;code&gt;x&lt;/code&gt; variable &amp;mdash; they are not actually separate copies. However, &lt;code&gt;anotherBlock&lt;/code&gt; does have its own separate &lt;code&gt;x&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;If you need a genuinely separate copy, recreate the block, don't copy it.&lt;/p&gt;

&lt;h4&gt;Blocks retain their NSObject scope variables&lt;/h4&gt;

&lt;p&gt;Blocks will &lt;code&gt;retain&lt;/code&gt; any &lt;code&gt;NSObject&lt;/code&gt; that they use from their enclosing scope when they are copied.&lt;/p&gt;

&lt;p&gt;The biggest implication of this is that you must remember to &lt;a href="http://cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html"&gt;avoid retain cycles&lt;/a&gt; if the block will be held beyond a simple stack lifetime.&lt;/p&gt;

&lt;p&gt;A &lt;a href="http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-14-practical-blocks.html"&gt;pointed out elsewhere&lt;/a&gt;, you can suppress this retain of &lt;code&gt;NSObject&lt;/code&gt;s by assigning the object to a &lt;code&gt;__block&lt;/code&gt; variable outside the block and only ever using the &lt;code&gt;__block&lt;/code&gt; variable inside the block.&lt;/p&gt;

&lt;p&gt;You can also do the reverse of this and force a pointer that isn't an &lt;code&gt;NSObject&lt;/code&gt; derived class to be retained when copied. Do this by declaring the pointer with &lt;code&gt;__attribute__((NSObject))&lt;/code&gt;. Of course, the situations where you'd want to do this are exceedingly rare.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Blocks are very simple to use in the case where you declare one inline and immediately pass into another function but once you need to copy or hold onto a block for a while, there are a number of quirks, some of which I've covered in this post.&lt;/p&gt;

&lt;p&gt;Sadly at this time, &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html"&gt;Apple's documentation on blocks&lt;/a&gt; is fairly basic and lacking in detail. This is what led me to start looking at clang's source code.&lt;/p&gt;

&lt;p&gt;Of course, you don't need to stare at someone else's C++ code to learn about blocks. There are other sources of lighter, more approachable documentation on the topic. In addition to sources that I've already linked, there's also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mike Ash's colorfully titled "&lt;a href="http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html"&gt;Friday Q&amp;A 2008-12-26&lt;/a&gt;" &amp;mdash; an excellent run-down of potential use-cases for blocks in Objective-C.&lt;/li&gt;
&lt;li&gt;Joachim Bengtsson's &lt;a href="http://thirdcog.eu/pwcblocks/"&gt;Programming with C Blocks&lt;/a&gt; &amp;mdash; a good general summary of most aspects of blocks&lt;/li&gt;
&lt;li&gt;Jim Dovey's Blocks &lt;a href="http://alanquatermain.net/post/138827791/blocks-episode-2-life-cycles"&gt;Episode 2: Life Cycles&lt;/a&gt; &amp;mdash; a look at stack and heap allocation of blocks with diagrams&lt;/li&gt;
&lt;li&gt;clang's &lt;a href="http://clang.llvm.org/docs/BlockLanguageSpec.txt"&gt;BlockLanguageSpec&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-2347122604201755491?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/xuAyBRv2qiI" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/2347122604201755491?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/2347122604201755491?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/xuAyBRv2qiI/how-blocks-are-implemented-and.html" title="How blocks are implemented (and the consequences)" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IDSXw_eyp7ImA9WxBQEkg.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-565887544693158621</id><published>2009-10-12T01:47:00.001-07:00</published><updated>2010-01-11T17:26:18.243-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-11T17:26:18.243-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Standard C" /><title>Objective-C's niche: why it survives in a world of alternatives</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Objective-C remains an impediment for many programmers coming to the Mac or iPhone platforms &amp;mdash; few programmers have ever experienced it before learning Cocoa, forcing two learning curves at once for new Cocoa developers. How did Apple end up with such a weird language? And for a company known to replace CPU architectures and their entire operating system, why does Apple persist with Objective-C? The answer lies in the methods.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Virtual methods&lt;/h4&gt;

&lt;p&gt;Most compiled, object-oriented languages (like C++, Java and C&amp;#9839;) adhere closely to the object-oriented approaches first introduced in &lt;a href="http://en.wikipedia.org/wiki/Simula"&gt;Simula 67&lt;/a&gt; &amp;mdash; in particular the concept of &lt;a href="http://en.wikipedia.org/wiki/Virtual_function"&gt;virtual methods&lt;/a&gt; and how they enable methods to be overridden.&lt;/p&gt;

&lt;blockquote style="width:40%;float:right;font-size:12px;margin-left:10px;"&gt;&lt;strong&gt;Origins in Algol:&lt;/strong&gt; In much the same way that Objective-C is often called a "pure superset" of C, Simula 67 was a "pure superset" of &lt;a href="http://en.wikipedia.org/wiki/ALGOL"&gt;Algol 60&lt;/a&gt;. While &lt;a href="http://en.wikipedia.org/wiki/Fortran"&gt;Fortran&lt;/a&gt; is sometimes remembered as the first high-level language to gain popularity (and disdain), Algol 60 was the first programming language to actually resemble a modern language as it contained the &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt;, &lt;code&gt;while,&lt;/code&gt; &lt;code&gt;return&lt;/code&gt; and other procedural contructs that are expected now in programming languages. While Algol was rarely used past the 1970's, &lt;a href="http://en.wikipedia.org/wiki/Pascal_(programming_language)"&gt;Pascal&lt;/a&gt; and its descendants closely resemble Algol in syntax.&lt;/blockquote&gt;

&lt;p&gt;In a compiled language, a &lt;a href="http://en.wikipedia.org/wiki/Subroutine"&gt;regular function&lt;/a&gt; (non-overrideable) ends up as a basic memory address. When the function is invoked, the CPU jumps to the memory address.&lt;/p&gt;

&lt;p&gt;Simula 67 introduced &lt;a href="http://en.wikipedia.org/wiki/Virtual_table"&gt;virtual method tables&lt;/a&gt; to adapt this for object-orientation. Instead of basic memory addresses, methods are compiled to row numbers in a table. To get the memory address, the method table is retrieved from the class of the object and the CPU jumps to the address at the specified row.&lt;/p&gt;

&lt;p&gt;Since different objects have different classes, they will have different addresses in their method tables, hereby allowing sublcasses to have different implementations of methods (&lt;a href="http://en.wikipedia.org/wiki/Method_overriding"&gt;method overrides&lt;/a&gt;) to their base classes.&lt;/p&gt;

&lt;h4&gt;Message passing&lt;/h4&gt;

&lt;p&gt;While virtual method tables do introduce a level of indirection that allows method behavior to change from object to object, the offsets into the table and hence the tables themselves all need to be created at compile-time.&lt;/p&gt;

&lt;blockquote style="width:40%;float:right;font-size:12px;margin-left:10px;"&gt;&lt;strong&gt;History of message passing:&lt;/strong&gt; As with object-orientation itself, message passing was inspired by Simula 67 but Simula's message passing (called "Simulation") wasn't for method invocations &amp;mdash; it was instead used for discrete event simulation (mostly queueing and list processing). &lt;a href="http://en.wikipedia.org/wiki/Smalltalk"&gt;Smalltalk&lt;/a&gt; expanded upon this idea by using message passing for method invocation. Smalltalk subsequently inspired the &lt;a href="http://en.wikipedia.org/wiki/Actor_model"&gt;Actor Model&lt;/a&gt; (used in distributed processing) and &lt;a href="http://en.wikipedia.org/wiki/Remote_procedure_call"&gt;remote procedure calls&lt;/a&gt; (RPC). Originally, Smalltalk messages were conceived to have a large amount of metadata (more like the full headers on an email) but eventually, this was simplified down to an approach syntactically similar to Objective-C's current implementation (minus square brackets).&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Message_passing"&gt;Message passing&lt;/a&gt; presents an alternative way of solving the &lt;a href="http://en.wikipedia.org/wiki/Dynamic_dispatch"&gt;method dispatch problem&lt;/a&gt;. Instead of the virtual method's compile-time offsets and tables which don't consult the object (except for its type), message passing sends a unique message identifier to the object itself and the object determines at runtime what action to take.&lt;/p&gt;

&lt;p&gt;Message passing approaches may still have a virtual method table ("vtable") in the class' representation but this structure is not known at compile time &amp;mdash; it is handled entirely at runtime &amp;mdash; and instances of the class have the opportunity to take different actions in response to the message that are unrelated to the content of the table.&lt;/p&gt;

&lt;p&gt;There are two important differences here:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Runtime resolution &amp;mdash; so the connection between message identifier and action can be changed at runtime.&lt;/li&gt;
&lt;li&gt;Involvement of the object itself, not just its class.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;On a technical level, the difference between a virtual method table and passing a message identifier is relatively minor (since both are really table lookups and both are actually performed at runtime). The difference ends up being conceptual:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Virtual method table languages generally make it hard or impossible to change the virtual method table contents or pointers at runtime.&lt;/li&gt;
&lt;li&gt;Type safety is essential in a virtual method table language since the compiler may alter table lookups based on type, particularly in cases of multiple inheritance. In message passing systems, type safety is irrelevant to method invocation.&lt;/li&gt;&lt;/ul&gt;

&lt;h4&gt;Why this matters&lt;/h4&gt;

&lt;p&gt;The short answer is that this dynamic message handling in Objective-C makes it much easier to work within a large framework that you didn't create because you can examine, patch and modify elements of that framework on the fly. The most common situation where this is likely to occur is when dealing with an &lt;a href="http://en.wikipedia.org/wiki/Application_framework"&gt;application framework&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The biggest reason for this is that you can add or change methods on existing objects, without needing to subclass them, while they are running. Approaches for this include &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocCategories.html#//apple_ref/doc/uid/TP30001163-CH20-TPXREF141"&gt;categories&lt;/a&gt;, &lt;a href="http://cocoawithlove.com/2008/03/supersequent-implementation.html"&gt;method swizzling&lt;/a&gt; and isa-swizzling.&lt;/p&gt;

&lt;p&gt;This makes the following situations possible:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;You want to add a convenience method to someone else's object (a quick search of my own posts reveals that about a dozens of my own posts involve adding convenience methods to Cocoa classes, e.g. &lt;a href="http://cocoawithlove.com/2008/08/safely-fetching-nsmanagedobject-by-uri.html"&gt;Safely fetching an NSManagedObject by URI&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;You want to change the behavior of a class you didn't (and can't) allocate because it is created by someone else (this is how &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/KeyValueObserving/Concepts/KVOImplementation.html"&gt;Key-Value Observing is implemented in Cocoa&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;You want to treat objects generically and handle potential differences with runtime introspection.&lt;/li&gt;
&lt;li&gt;You want to substitute an object of a completely different class to the expected class (this is used in Cocoa by &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSProxy_Class/Reference/Reference.html"&gt;NSProxy&lt;/a&gt; to turn a regular object into a distributed object).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These points may seem somewhat mild but they are central to maximizing code reuse when working within someone else's framework: if you need existing code to work differently, you don't need to reimplement the whole class and you don't need to change how it is allocated.&lt;/p&gt;

&lt;p&gt;Languages using virtual method tables can adopt some of these ideas (like the &lt;a href="http://www.boost.org/doc/libs/1_40_0/doc/html/boost/any.html"&gt;boost::any&lt;/a&gt; class or &lt;a href="http://en.wikipedia.org/wiki/C_Sharp_4.0"&gt;C&amp;#9839; 4.0's dynamic member lookup&lt;/a&gt;) but these features have additional restrictions and don't apply to all objects, meaning that they can't be used on purely arbitrary objects (such as those you don't control or didn't create) and so don't help when interacting with someone else's framework.&lt;/p&gt;

&lt;p&gt;Simply put: dynamic message passing instead of virtual method invocations makes Objective-C a much better language for working with a large library or framework that someone has written.&lt;/p&gt;

&lt;h4&gt;The tradeoff&lt;/h4&gt;

&lt;p&gt;The downside to dynamic message invocation is that it is only as fast as virtual method invocation when the message lookup is cached, otherwise it is invariably slower.&lt;/p&gt;

&lt;p&gt;Also, in keeping with the philosophy of a purely dynamic messaging system, Objective-C does not use templates or template metaprogramming and does not have non-dynamic (i.e. non-virtual) methods. This means that Objective-C methods will miss out on the compiler optimizations possible when employing these techniques. Also, since modern programming in C++ is substantially focussed on these features, it can difficult to adapt programs using these ideas to Objective-C.&lt;/p&gt;

&lt;p&gt;Theoretically, Objective-C could implement these features but they are in opposition to the underlying concepts of flexibility and dynamic behavior in Objective-C &amp;mdash; and would shut-down all advantages from the previous section if they were used.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;It's not a coincidence that I write an Objective-C/Cocoa blog, I'm obviously an advocate of Objective-C and Cocoa. In my opinion, Objective-C is the best language for programming situations where you must make extensive use of a framework written by someone else (particularly an application framework). The success of Objective-C in this situation is due to the combination of:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;speed and precision (from its compiled C roots)&lt;/li&gt;
&lt;li&gt;dynamic flexibility (due to using message passing for method invocations)&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;To frame this conclusion, I'll state that I've written major projects using C/WIN32, C++/PowerPlant, C++/MFC, and Java/Swing/AWT. I've also dabbled in smaller projects using C&amp;#9839;/.Net. In all of these cases I have found the application frameworks to be less flexible and less reusable because they lack the dynamic modifiability of Objective-C.&lt;/p&gt;

&lt;p&gt;As I've stated, I do view Objective-C's strength in the area of application frameworks as a niche (albeit a very large niche). If I were writing a compiler, OS kernel, or a low-level/high-performance library, then I would use C++ (I wouldn't use pure C because I'd miss my abstractions) &amp;mdash; but these are situations where metaprogramming, greater inlining and faster method invocations would trump flexibility concerns. Of course, if you have a project that needs to satisfy all these criteria: then there's always Objective-C++.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-565887544693158621?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/y4mSqJD5Kx8" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/565887544693158621?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/565887544693158621?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/y4mSqJD5Kx8/objective-c-niche-why-it-survives-in.html" title="Objective-C&amp;#39;s niche: why it survives in a world of alternatives" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/10/objective-c-niche-why-it-survives-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIFRH8-fip7ImA9WxNXGEU.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-5233290619796143454</id><published>2009-10-05T20:20:00.001-07:00</published><updated>2009-10-06T21:08:35.156-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-06T21:08:35.156-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Snow Leopard" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Standard C" /><title>The ugly side of blocks: explicit declarations and casting.</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Blocks are a welcome addition to C/Objective-C/C++/Objective-C++ with Snow Leopard but they carry with them the worst aspect of Standard C: function pointer declaration and casting syntax. In this post, I'll show you how to understand declarations and casting syntax for blocks and function pointers, even in the worst of scenarios.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Simple block declarations and casting&lt;/h4&gt;

&lt;p&gt;Used as intended (simple inline code implementations) blocks are fairly elegant. This is due to one advantage they offer: in simple cases, you do not need to specify the return type &amp;mdash; it can be inferred from the return statement in the block itself.&lt;/p&gt;

&lt;p&gt;So declaring a block that returns an &lt;code&gt;int&lt;/code&gt; can be as simple as:&lt;/p&gt;

&lt;pre&gt;int (^alwaysReturnIntZero)() = ^{ return 0; };&lt;/pre&gt;

&lt;p&gt;In this case though, an unqualified integral value is correctly assumed to be an &lt;code&gt;int&lt;/code&gt;. If we want the block to return an &lt;code&gt;NSInteger&lt;/code&gt;, we need to either cast the return type or not rely on type inference and declare the return fully:&lt;/p&gt;

&lt;pre&gt;NSInteger (^alwaysReturnNSIntegerZero)() = ^ NSInteger (){ return 0; };&lt;/pre&gt;

&lt;p&gt;Notice that the &lt;em&gt;block literal&lt;/em&gt; (righthand side) does not follow the structure as the &lt;em&gt;block declaration&lt;/em&gt; (lefthand side). The block literal uses a straightforward "caret, return type, parameter list" order but the block declaration uses the C function pointer declaration syntax, which can grow more complex (as I'll show later). At this point though, the two are of similar complexity.&lt;/p&gt;

&lt;p&gt;Casting a block looks much like declaring a block, minus the name of the variable from the declaration.&lt;/p&gt;

&lt;pre&gt;long long (^alwaysReturnLongLongZero)() = (long long (^)())alwaysReturnNSIntegerZero;&lt;/pre&gt;

&lt;p&gt;If you look at what is done here, all that is needed to create a cast for a value to the variable type, is to copy the variable's declaration, put parentheses around the copied declaration and remove the variable name.&lt;/p&gt;

&lt;h5&gt;Function pointers&lt;/h5&gt;

&lt;p&gt;Blocks borrow their syntax from standard C function pointers. In almost all cases, the only difference between a block declaration or cast and a function pointer declaration or cast is the "&lt;code&gt;^&lt;/code&gt;" character is used for the block and the "&lt;code&gt;*&lt;/code&gt;" character is used for the function pointer. e.g.:&lt;/p&gt;

&lt;pre&gt;long long (*fnAlwaysReturnLongLongZero)() = (long long (*)())fnAlwaysReturnNSIntegerZero;&lt;/pre&gt;

&lt;p&gt;Of course, functions cannot be declared inline, so you cannot have function literals in the same way as you can have block literals. However, all other syntactic traits remain the same.&lt;/p&gt;

&lt;h4&gt;Reading declarations correctly&lt;/h4&gt;

&lt;p&gt;Unfortunately, blocks follow the typical C declaration rules which become outright confusing when you try to return something. Before it all gets complicated, I'm going to explain something simple about C declarations.&lt;/p&gt;

&lt;p&gt;Consider how a pointer is declared:&lt;/p&gt;

&lt;pre&gt;int *myVariable;&lt;/pre&gt;

&lt;p&gt;If you're reading this blog at all, you should know that this statement creates a pointer named &lt;code&gt;myVariable&lt;/code&gt; which points to an &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But the operator used here is a "dereference", it is not the "make a pointer" (address of) operator. The correct way to read this line is:

&lt;ol&gt;
&lt;li&gt;Declare a variable:&lt;br/&gt;
	&lt;code&gt;myVariable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It can be dereferenced (and by &lt;em&gt;implication&lt;/em&gt; is therefore a pointer)&lt;br/&gt;
	&lt;code&gt;*myVariable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If it is deferenced, then the value yielded from the dereference should be treated as an &lt;code&gt;int&lt;/code&gt;:&lt;br/&gt;
	&lt;code&gt;int *myVariable;&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's look at the &lt;code&gt;alwaysReturnIntZero&lt;/code&gt; declaration from above again and we'll apply this same reading to it.&lt;/p&gt;

&lt;pre&gt;int (^alwaysReturnIntZero)() = ^{ return 0; };&lt;/pre&gt;

&lt;ol&gt;
&lt;li&gt;Declare a variable:&lt;br/&gt;
	&lt;code&gt;alwaysReturnIntZero&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It can be dereferenced to yield block information (and by &lt;em&gt;implication&lt;/em&gt; is therefore a block pointer):&lt;br/&gt;
	&lt;code&gt;^alwaysReturnIntZero&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Its block implementation takes no parameters and returns an &lt;code&gt;int&lt;/code&gt;:&lt;br/&gt;
	&lt;code&gt;int (^alwaysReturnIntZero)()&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach to reading a declaration is quite simple but you'll need to it to follow the next section.&lt;/p&gt;

&lt;h4&gt;Declaring a block that returns a block&lt;/h4&gt;

&lt;p&gt;Imagine you wanted to use a block to compare a &lt;code&gt;double&lt;/code&gt; to an &lt;code&gt;int&lt;/code&gt; and return &lt;code&gt;true&lt;/code&gt; if the &lt;code&gt;double&lt;/code&gt; is greater than the &lt;code&gt;int&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; if the double is equal or smaller. In the simple case, that might look like this:&lt;/p&gt;

&lt;pre&gt;bool (^compareDoubleToInt)(int i, double j) = ^{ return j &gt; i; };&lt;/pre&gt;

&lt;p&gt;Easy enough but imagine now that you want to break this into two pieces:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;A first block which takes only the &lt;code&gt;int&lt;/code&gt; and returns a second block, pre-configured to use this &lt;code&gt;int&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The second block then takes the &lt;code&gt;double&lt;/code&gt;, compares it to its pre-configured &lt;code&gt;int&lt;/code&gt; and returns the result.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;The first block is then a &lt;em&gt;factory block&lt;/em&gt; which creates instances of the second block that operate like the &lt;code&gt;compareDoubleToInt&lt;/code&gt; shown above for a single, pre-configured value of &lt;code&gt;i&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The complete implemention of this would be:&lt;/p&gt;

&lt;pre&gt;bool (^(^newDoubleToIntComparison)(int))(double) =
    ^(int i)
    {
        return Block_copy(^ (double j)
        {
            return j &gt; i;
        });
    };&lt;/pre&gt;

&lt;blockquote&gt;Pay careful attention to the "new" in the name &amp;mdash; this serves to notify that you must use &lt;code&gt;Block_destroy&lt;/code&gt; on any blocks created in this fashion when you're done.&lt;/blockquote&gt;

&lt;p&gt;If everything about the syntax on that first line (the declaration) makes immediate sense to you, then you may consider yourself skilled at syntactic recursion.&lt;/p&gt;

&lt;p&gt;The reason most people find this hard to read is that verbally, we would describe this scenario in a very different order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Declare a variable:&lt;br/&gt;&lt;code&gt;newDoubleToIntComparison&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It can be dereferenced to yield block information (and by &lt;em&gt;implication&lt;/em&gt; is therefore a block pointer):&lt;br/&gt;
&lt;code&gt;^newDoubleToIntComparison&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The block takes an &lt;code&gt;int&lt;/code&gt; parameter:&lt;br/&gt;&lt;code&gt;(^newDoubleToIntComparison)(int)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Its return value can be dereferenced to yield block information (and by &lt;em&gt;implication&lt;/em&gt; the return value is therefore a block pointer):&lt;br/&gt;
&lt;code&gt;(^(^newDoubleToIntComparison)(int))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;This returned block takes a &lt;code&gt;double&lt;/code&gt; parameter&lt;br/&gt;&lt;code&gt;(^(^newDoubleToIntComparison)(int))(double)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;And the returned block returns a &lt;code&gt;bool&lt;/code&gt;&lt;br/&gt;&lt;code&gt;bool (^(^newDoubleToIntComparison)(int))(double);&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;If C declarations read from left-to-right, it would be far less confusing. Instead, we have a situation where blocks that return blocks are recursively nested inside each other.&lt;/p&gt;

&lt;p&gt;Of course, most people mitigate this by &lt;code&gt;typedef&lt;/code&gt;'ing absolutely function pointer they ever use. Doing this for the previous block declaration changes it to:&lt;/p&gt;

&lt;pre&gt;typedef bool (^IsDoubleBiggerBlock)(double);
IsDoubleBiggerBlock (^newDoubleToIntComparison)(int);&lt;/pre&gt;

&lt;h4&gt;Functions or methods that return blocks&lt;/h4&gt;

&lt;p&gt;It may also be helpful to see the subtle difference between declaring a block that returns a block and the definition of of a function returns a block.&lt;/p&gt;

&lt;p&gt;Replacing the &lt;em&gt;factory block&lt;/em&gt; with a &lt;em&gt;factory function&lt;/em&gt; in the previous example would lead to:&lt;/p&gt;

&lt;pre&gt;bool (^NewDoubleToIntComparisonFunction(int i))(double)
{
    return (bool (^)(double))Block_copy(^ (double j)
    {
        return j &gt; i;
    });
};&lt;/pre&gt;

&lt;p&gt;This function takes a single &lt;code&gt;int&lt;/code&gt; as its parameter and yet the last component on the function prototype line is &lt;code&gt;(double)&lt;/code&gt;. The &lt;code&gt;int&lt;/code&gt; parameter that the function actually takes and the name of the function are nested inside of the return type (the return type comprises the &lt;code&gt;double&lt;/code&gt; parameter to the right, the caret character and the &lt;code&gt;bool&lt;/code&gt; return value to the left).&lt;/p&gt;

&lt;p&gt;Also notice that you need to cast the output of &lt;code&gt;Block_copy&lt;/code&gt; to have it recognized as the correct return type.&lt;/p&gt;

&lt;p&gt;As with the variable declarations, this nested behaviour is normally considered too annoying, so typedefs are employed to simplify:&lt;/p&gt;

&lt;pre&gt;typedef bool (^IsDoubleBiggerBlock)(double);
IsDoubleBiggerBlock NewDoubleToIntComparisonFunction(int i)
{
    return (IsDoubleBiggerBlock)Block_copy(^ (double j)
    {
        return j &gt; i;
    });
};&lt;/pre&gt;

&lt;p&gt;This has the huge advantage that it puts the function's parameter back where it belongs &amp;mdash; as the last component on the function prototype line.&lt;/p&gt;

&lt;p&gt;An Objective-C method that returns a block is a much simpler situation since the method does not become nested within the return type in the same way. Instead, the return type looks identical to the cast of the returned copied block and the rest of the method remains distinct.&lt;/p&gt;

&lt;pre&gt;- (bool (^)(double))newDoubleToIntComparison:(int)i
{
    return (bool (^)(double))Block_copy(^ (double j)
    {
        return j &gt; i;
    });
}&lt;/pre&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;The declaration of C function pointers is widely regarded as the worst syntax in the language. There is a good reason for this: the information in a function pointer's declaration flows from the most significant components which are nestled on the inside of the declaration to the least significant components which encircle the outside. They could flow left-to-right like a sentence but instead they flow outwards from an identifier somewhere in the middle.&lt;/p&gt;

&lt;p&gt;Sadly, blocks follow in this tradition. All you can do to mitigate the torment is use &lt;code&gt;typedef&lt;/code&gt;'d declarations judiciously and try to keep your blocks simple. They're not really intended for large numbers of parameters and complex return values, anyway.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-5233290619796143454?l=cocoawithlove.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CocoaWithLove/~4/gX8mVPXn_7Q" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/5233290619796143454?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/5233290619796143454?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CocoaWithLove/~3/gX8mVPXn_7Q/ugly-side-of-blocks-explicit.html" title="The ugly side of blocks: explicit declarations and casting." /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author><feedburner:origLink>http://cocoawithlove.com/2009/10/ugly-side-of-blocks-explicit.html</feedburner:origLink></entry></feed>
