<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ben Reimers</title>
	<atom:link href="http://benreimers.net.au/feed" rel="self" type="application/rss+xml" />
	<link>http://benreimers.net.au</link>
	<description>A design and development blog.</description>
	<lastBuildDate>Sat, 25 Feb 2012 02:16:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Cocos2D, AI, and a simple Asteroids clone</title>
		<link>http://benreimers.net.au/blog/cocos2d-ai-and-a-simple-asteroids-clone</link>
		<comments>http://benreimers.net.au/blog/cocos2d-ai-and-a-simple-asteroids-clone#comments</comments>
		<pubDate>Sat, 25 Feb 2012 02:12:10 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Cocos2D]]></category>
		<category><![CDATA[Game Dev]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://benreimers.net.au/?p=74</guid>
		<description><![CDATA[Things have been a bit hectic at work lately and I couldn’t really devote as much time to programming as I would like. That said, I have managed to spend a bit of time taking a detour and learning a &#8230; <a href="http://benreimers.net.au/blog/cocos2d-ai-and-a-simple-asteroids-clone">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Things have been a bit hectic at work lately and I couldn’t really devote as much time to programming as I would like. That said, I have managed to spend a bit of time taking a detour and learning a some game development.</p>
<p>Without a framework, game development on iOS would involve low-level interaction with the OpenGL api. That’s not an easy task, although it is possible. First of all there’s working with C libraries where functions often have cryptic names—Objective-C might be verbose, but at least you can get an understanding of the code just by looking at it, but standard C is almost impossible to decipher if you’re unfamiliar with it. Then there’s managing memory, which even professional developers have trouble doing consistently without causing leaks.</p>
<p>Thankfully, the Cocos2D framework abstracts away all of that low-level stuff and most of the memory management and provides an Objective-C object model to make games. While game development is still more involved than general app dev, it’s still much easier with the middle-man in place.</p>
<p><a href="http://benreimers.net.au/wp-content/uploads/2012/02/photo.png"><img class="alignnone size-medium wp-image-75" title="photo" src="http://benreimers.net.au/wp-content/uploads/2012/02/photo-300x225.png" alt="" width="300" height="225" /></a></p>
<p>After working through the first few chapters of <a href="http://cocos2dbook.com/book/">Learning Cocos2D (etc.)</a> I was able to throw together this quick and dirty Asteroids clone for iPad. Ignore the graphics and interface at the moment, I did say it was quick. The ship doesn’t move as I would like at the moment, since it’s just mapped 1-1 with the joystick control on the left (that’s why it’s pointing away from the bullets in the screenshot: I had to take my thumb off the joystick to take it) but everything else works.</p>
<p>I do actually have an idea of a way to expand this into a full game that’s no longer Asteroids but a sort of top-down competitive shooter. The tricky part will be figuring out if having two people holding an iPad between them to compete against each other is a feasible control method. I’ve also been delving a bit into some real-time AI methodology so you’d also be able to play against the computer.</p>
<p>Anyway, I’ve been finding the AI part really interesting. Just learning about the different techniques that some of my favourite games use to give the impression of intelligence is fascinating. Putting them into practice will be a lot harder, but it’s something to work towards.</p>
]]></content:encoded>
			<wfw:commentRss>http://benreimers.net.au/blog/cocos2d-ai-and-a-simple-asteroids-clone/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Saving and loading data: NSCoding and NSKeyedArchiver</title>
		<link>http://benreimers.net.au/blog/saving-and-loading-data-nscoding-and-nskeyedarchiver</link>
		<comments>http://benreimers.net.au/blog/saving-and-loading-data-nscoding-and-nskeyedarchiver#comments</comments>
		<pubDate>Thu, 26 Jan 2012 02:51:49 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://benreimers.net.au/?p=72</guid>
		<description><![CDATA[There are several ways to store data for Cocoa applications. You could implement your own file loading and saving methods and store the data in any number of formats you want, but it’s time-consuming. You could use Cocoa’s built-in database &#8230; <a href="http://benreimers.net.au/blog/saving-and-loading-data-nscoding-and-nskeyedarchiver">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>There are several ways to store data for Cocoa applications. You could implement your own file loading and saving methods and store the data in any number of formats you want, but it’s time-consuming. You could use Cocoa’s built-in database functionality, called <em>Core Data</em>, but that’s not ideal for everything and it’s very hands-off in its approach.</p>
<p>If you decide to store your data outside of a database, it would be great if Cocoa provided a means to easily manage files and get your data into them, without having to do any of the low-level stuff.</p>
<p>That’s where the <em>NSKeyedArchiver</em> comes in.</p>
<h2>Archiving and unarchiving data</h2>
<p>When Cocoa refers to archiving data, it doesn’t mean making a compressed <em>zip</em> file, it means putting all the relevant data together and then saving it to a single file. These files have a certain structure that Cocoa can then unarchive. The archiving takes place via the <em>NSKeyedArchiver</em> object, and is read back via the (you guess it!) <em>NSKeyedUnarchiver</em>.</p>
<p>The way <em>NSKeyedArchiver</em> works is by taking a “root” object. This object will know what information needs to be stored, and “tells” the <em>NSKeyedArchiver</em> what it is and how to do it. The information is stored using string keys so that it can be retrieved using the same keys.</p>
<p>Now, the root object could be an array (like it is with my Todo app) or it could be an object that contains an array and links to other objects. The thing all of these have in common is that must know how to give the <em>NSKeyedArchiver</em> the correct information to do its job.</p>
<p>They do this by conforming to the <em>NSCoding</em> protocol.</p>
<h2>Saving data to a file</h2>
<p>The first thing that needs to happen when attempting to save our objects is to implement the method in the <em>NSCoding</em> protocol that our coder (<em>NSKeyedArchiver</em>) expects to find, <strong>encodeWithCoder:</strong></p>
<p>Here it is for our base object, <em>TaskStore.</em></p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>encodeWithCoder<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSCoder</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>coder
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>coder encodeObject<span style="color: #002200;">:</span>taskStore forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;taskStore&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>This is pretty simple, but our <em>TaskStore</em> object only has one property, <em>taskStore</em>, which is an array of our root groups (sections).</p>
<p>As you can see, all we need to do encode our array is call <strong>encodeObject:forKey:</strong> on our coder object. Arrays conform to the <em>NSCoding</em> protocol, so they know how to encode themselves; we don’t need to iterate through arrays, but they do assume that the objects contained in them conform to <em>NSCoding</em> as well.</p>
<p>Here is the <strong>encodeWithCoder:</strong> method for our <em>TaskGroup</em> object:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>encodeWithCoder<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSCoder</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>coder
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>coder encodeObject<span style="color: #002200;">:</span>name forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>coder encodeObject<span style="color: #002200;">:</span>subgroups forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;subgroups&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>coder encodeObject<span style="color: #002200;">:</span>tasks forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;tasks&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>coder encodeBool<span style="color: #002200;">:</span>expanded forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;expanded&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>The difference here is that <em>TaskGroup</em> is more complex, with a number of different properties: an <em>NSString</em>, two <em>NSMutableArrays</em>, and a BOOL. The string and arrays can both call <strong>encodeObject:forKey:</strong> because they are Cocoa objects that conform to <em>NSCoding</em>.</p>
<p>The boolean, on the other hand, is a primitive C type and needs to be handled separately, which is why it has it’s own method (<strong>encodeBool:forKey:</strong>) on the coder. You would need to call any of the relevant methods for the other C types as well, like <em>int</em> or <em>float</em>.</p>
<p>I will leave the method of the tasks themselves up to your imagination.</p>
<p>Now that our objects know how to encode themselves, we need to get our <em>NSKeyedArchiver</em> to do so. We’ll implement the relevant methods on our <em>TaskStore</em> because it’s the root object. Once it initiates the load, it can read in the rest of the object tree.</p>
<p>First we’ll have a method that gives us a standard file location. This should probably be externalised to a settings file, but for such a simple project we’ll hardcode the file location (in the user Library).</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> pathForDataFile
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSFileManager</span> <span style="color: #002200;">*</span>fileManager <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSFileManager</span> defaultManager<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>folder <span style="color: #002200;">=</span> LIBRARY_PATH;
    folder <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>folder stringByExpandingTildeInPath<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>fileManager fileExistsAtPath<span style="color: #002200;">:</span>folder<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #a61390;">NO</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>fileManager createDirectoryAtPath<span style="color: #002200;">:</span>folder withIntermediateDirectories<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span> attributes<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>fileName <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;WhatNow.taskStore&quot;</span>;
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>folder stringByAppendingPathComponent<span style="color: #002200;">:</span> fileName<span style="color: #002200;">&#93;</span>;    
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>All this does is check to see if the our program folder (LIBRARY_PATH, a constant declared at the beginning of the file) exists, creates it if it doesn’t, and then returns a string to the file including the full folder path.</p>
<p>We then need a method to use <em>NSKeyedArchiver</em> to save it to disk:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>saveDataToDisk
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span> path <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self pathForDataFile<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span>rootObject;
    rootObject <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableDictionary</span> dictionary<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>rootObject setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self taskStore<span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;taskStore&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSKeyedArchiver</span> archiveRootObject<span style="color: #002200;">:</span>rootObject toFile<span style="color: #002200;">:</span> path<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>The method we call on <em>NSKeyedArchiver</em> is a class method (there’s no reason to create an object from it). We first have to put our array into an <em>NSMutableDictionary</em>, but we could also put in other objects that are separate from our <em>TaskStore</em> if we wanted. If this were a document-based application, we might have document-specific settings, for example.</p>
<p>Anyway, this method is called from our Application Delegate whenever the app is closed. Because this is not a document-based app, auto-saving will need to be implemented separately.</p>
<p>That’s it for saving data. Our <strong>saveDataToDisk:</strong> method tells the shared <em>NSKeyedArchiver</em> to start saving data on our root array. The array iterates through the groups and tells them to encode. The groups tell their subgroups to encode, and all of the leaf groups tell the tasks to encode.</p>
<p>Now that saving works, we need to go the other way and rebuild the object tree from the file.</p>
<h2>Reading data from a file</h2>
<p>When we make our objects conform to <em>NSCoding</em>, they need to know how to initialise themselves not only when being created from scratch but also when being initialised from the file via <em>NSKeyedUnarchiver</em>. To do this, they need a new initialisation method called <strong>initWithCoder:</strong></p>
<p>Here is the method for our base object, <em>TaskStore</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithCoder<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSCoder</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>coder
<span style="color: #002200;">&#123;</span>
    self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>self<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        taskStore <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>coder decodeObjectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;taskStore&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>This one is quite simple and is basically the reverse of what we did to encode it. <strong>decodeObjectForKey:</strong> will return, in this instance, an array and we simply assign it to our instance variable. If we decoded the wrong key, it would raise an exception.</p>
<p>Our <em>TaskGroup</em> object is a little more complicated, but not by a whole lot:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithCoder<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSCoder</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>coder
<span style="color: #002200;">&#123;</span>
    self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>self<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>self setName<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>coder decodeObjectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>self setSubgroups<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>coder decodeObjectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;subgroups&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>self setTasks<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>coder decodeObjectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;tasks&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>self setExpanded<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>coder decodeBoolForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;expanded&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>Same as for the root object. Again, the boolean has its own method, <strong>decodeBoolForKey:</strong> because it is a primitive type. In this case we use the accessor method to assign the values because I’ve only set them up as properties, not with instance variable as well.</p>
<p>As with encoding, I’ll leave decoding the task to your imagination.</p>
<p>We also need to tell <em>NSKeyedUnarchiver</em> to get the data for us:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>loadDataFromDisk
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSString</span>     <span style="color: #002200;">*</span> path        <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self pathForDataFile<span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span> rootObject;
&nbsp;
    rootObject <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSKeyedUnarchiver</span> unarchiveObjectWithFile<span style="color: #002200;">:</span>path<span style="color: #002200;">&#93;</span>;    
    <span style="color: #002200;">&#91;</span>self setTaskStore<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>rootObject valueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;taskStore&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>We call this method when the application starts.</p>
<p>And that’s it for saving and loading to a file. The <em>NSKeyedUnarchiver</em> will tell the root object to decode from the file. The root object will unarchive all of it’s objects (in the array), which will then unarchive its object, ending up with exactly the same object tree that was saved.</p>
]]></content:encoded>
			<wfw:commentRss>http://benreimers.net.au/blog/saving-and-loading-data-nscoding-and-nskeyedarchiver/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Concepts: Delegation and protocols</title>
		<link>http://benreimers.net.au/blog/concept-delegation-and-protocols</link>
		<comments>http://benreimers.net.au/blog/concept-delegation-and-protocols#comments</comments>
		<pubDate>Mon, 23 Jan 2012 10:17:04 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Concepts]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://benreimers.net.au/?p=66</guid>
		<description><![CDATA[One concept that pops up frequently in Cocoa programming is that of delegation. In fact, we’ve already seen that concept in my previous post about NSOutlineView. We set the delegate of our NSOutlineView to be the TodoController. We also set &#8230; <a href="http://benreimers.net.au/blog/concept-delegation-and-protocols">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One concept that pops up frequently in Cocoa programming is that of delegation. In fact, we’ve already seen that concept in my previous post about <em>NSOutlineView</em>. We set the delegate of our <em>NSOutlineView</em> to be the <em>TodoController</em>. We also set the data source to be <em>TodoController</em>—a data source is just another delegate.</p>
<p>A delegate is described as a person who acts on behalf of another, and this is pretty much exactly what it sounds like in Cocoa. When we set a delegate (or data source) of an object which accepts one, we’re telling the object to pass a certain amount of control over to the object we specify. The delegate is acting on behalf of (performing some of the function of) the original object.</p>
<p>That’s all well and good, but how does the delegate know what to do? That’s where protocols come in.</p>
<p>In Objective-C, protocols describe the methods that delegates can or must implement in order to perform the activities they’ve been delegated to do. They don’t have to implement those methods, but incomplete implementations may mean that things don’t work correctly. This is particularly important for things like data sources, where they’re asked to provide actual data to be displayed to the screen: if you don’t implement them right, the data doesn’t get delivered.</p>
<p>Once we’ve implemented those methods, and set our delegates correctly (either in Interface Builder or programmatically), our original object can then call those methods on the delegate to handle those functions.</p>
<p>In the case of our <em>NSOutlineView</em>, one of those methods was <strong>outlineView:viewForTableColumn:item:</strong>. This method took the task of creating a view which could be returned to the <em>NSOutlineView</em> to be displayed on the screen. If we didn’t implement this method, as we found out, nothing would appear on the screen; it’s a required method for <em>NSOutlineViewDelegate</em> protocol.</p>
<p>Although there are four required delegate methods to programmatically get an <em>NSOutlineView</em> to display data, there are many other methods that can be implemented to customise the behaviour of the outline view. One of these methods is, for example, <strong>outlineViewItemDidExpand:</strong>. If we implemented this method in our delegate, we can customise the behaviour or perform certain actions that happen after a group is expanded. We will actually need to do this in order to store the expanded state with our groups. This method is not required—leaving it out will have no effect on the function of the outline view—but implementing it gives us greater control over the function of our application.</p>
<p>Anyway, that’s a basic rundown of how delegation and protocols work in Objective-C/Cocoa. It’s a very powerful way to customise function without subclassing objects.</p>
]]></content:encoded>
			<wfw:commentRss>http://benreimers.net.au/blog/concept-delegation-and-protocols/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sources lists and NSOutlineView</title>
		<link>http://benreimers.net.au/blog/sources-lists-and-nsoutlineview</link>
		<comments>http://benreimers.net.au/blog/sources-lists-and-nsoutlineview#comments</comments>
		<pubDate>Fri, 20 Jan 2012 02:00:51 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://benreimers.net.au/?p=60</guid>
		<description><![CDATA[First up on my list of tasks to perform is to set up the sidebar to display the groups and sections. When choosing from the elements in Interface Builder (IB), there are two options: Outline Views, or Source Lists. An &#8230; <a href="http://benreimers.net.au/blog/sources-lists-and-nsoutlineview">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>First up on my list of tasks to perform is to set up the sidebar to display the groups and sections. When choosing from the elements in Interface Builder (IB), there are two options: Outline Views, or Source Lists. An Outline View is a stock standard expandable/collapsible hierarchical listing. Source lists, on the other hand, or more like the sidebar in Mac Mail, with icons and headers for sections.</p>
<p>Naturally, the source list is what I’ve chosen. Technically, however, the source list is really an <em>NSOutlineView</em>, but is view-based rather than cell-based. This means that the cells are NSView objects, and can contain any elements you want. It also makes dealing with them a touch more difficult. From now on I will refer to the NSOutlineView and Source List to mean the same thing.</p>
<p>To get the data into the Source List, the custom controller class (TodoController) needs to be set as its delegate and data source. When the source list initialises or redraws, it will call methods on the data source to request certain information. These methods are: <strong>outlineView:isItemExpandable:</strong>, <strong>outlineView:numberOfChildrenOfItem:</strong>, <strong>outlineView:child:ofItem:</strong>, and <strong>outlineView:objectValueForTableColumn:byItem:</strong>.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>outlineView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSOutlineView</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>outlineView isItemExpandable<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>TodoGroup <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>item
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>item childGroups<span style="color: #002200;">&#93;</span> count<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&amp;</span>gt; <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>outlineView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSOutlineView</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>outlineView numberOfChildrenOfItem<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>TodoGroup <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>item
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>item <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>rootGroups count<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>item childGroups<span style="color: #002200;">&#93;</span> count<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>outlineView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSOutlineView</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>outlineView child<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>index ofItem<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>item
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>item <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>rootGroups objectAtIndex<span style="color: #002200;">:</span>index<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>item childGroups<span style="color: #002200;">&#93;</span> objectAtIndex<span style="color: #002200;">:</span>index<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>outlineView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSOutlineView</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>outlineView objectValueForTableColumn<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSTableColumn</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableColumn byItem<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>item
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>item groupName<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>The first two are used for information only, to help the outline view build its structure, with the first informing the view about whether it can be expanded (i.e. has child groups), and the second reporting how many children it has.</p>
<p>The third method is used to get a specific child group of an a section or parent group. The “child” variable is actually an integer that will directly correspond to the an index of the array where a child exists.</p>
<p>The last method was where everything was coming unstuck. It should have worked, but the code simply wasn’t being called. There was nothing in the data source protocol documentation that would point me to why it didn’t work, so it had me stumped. I tried copying code directly from the example code provided by Apple, but it still didn’t work (even though the example project ran fine).</p>
<p>Anyway, it turns out (after a frustrating hour or so of Google-fu and trial and error), that the necessary method to implement is not, in fact, a part of the data source, it is a part of the delegate. The reason for this is that NSOutlineView is based on NSTableView, which uses a delegate method to return the view for the cell.</p>
<p>So, for view-based outline views/source lists, we need to implement <strong>outlineView:viewForTableColumn:item:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSView</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>outlineView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSOutlineView</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>ov viewForTableColumn<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSTableColumn</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableColumn item<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>TodoGroup <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>item <span style="color: #002200;">&#123;</span>
&nbsp;
    NSTableCellView <span style="color: #002200;">*</span>result;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>item isHeaderGroup<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        result <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>ov makeViewWithIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;HeaderCell&quot;</span> owner<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        result <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>ov makeViewWithIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;DataCell&quot;</span> owner<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>result textField<span style="color: #002200;">&#93;</span> setStringValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>item groupName<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> result;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>And that’s it. When I plug in some sample data, it builds the source list correctly, finally! Now, this method will need to be modified down the track when I add a token to indicate the number of incomplete tasks, but for now it’s functionally usable.</p>
<p>Next stop is buttons to add and remove groups and sections from the list.</p>
]]></content:encoded>
			<wfw:commentRss>http://benreimers.net.au/blog/sources-lists-and-nsoutlineview/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What’s Next? A first project.</title>
		<link>http://benreimers.net.au/blog/whats-next-a-first-project</link>
		<comments>http://benreimers.net.au/blog/whats-next-a-first-project#comments</comments>
		<pubDate>Thu, 19 Jan 2012 06:56:05 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://benreimers.net.au/?p=46</guid>
		<description><![CDATA[I was originally thinking about jumping straight into developing my major idea. I even wrote up a list of features and have a screen layout sitting inside my head. Unfortunately, it’s probably a little too big for me to tackle &#8230; <a href="http://benreimers.net.au/blog/whats-next-a-first-project">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I was originally thinking about jumping straight into developing my major idea. I even wrote up a list of features and have a screen layout sitting inside my head. Unfortunately, it’s probably a little too big for me to tackle this early on.</p>
<p>There’s also a little problem: I tend to be terribly unorganised.</p>
<p>Writing up the feature list got me thinking about how I would manage the list itself, and everything else I set out to do. What I needed was some sort of task-management (other wise known as <em>Getting Things Done</em>) software. I know, I know, there’s plenty of them out there, but I either have to pay for them, or they don’t work the way I like work (usually both). Having other people solve my problems also doesn’t help me improve my programming skills.</p>
<p>So we have an idea for a first project: task-management.</p>
<p>This project will be fairly simple. Tasks will belong to groups, and groups to sections. The sections will be things like “Projects” and “Home Tasks”. Groups will be things like major projects or planning for our next holiday. These can be split into any number of levels: individual projects could have task groups for interface design, development, testing, etc.</p>
<p>Tasks will have optional completion dates, but the aim of the program isn’t to act as a scheduler: we have iCal for that. I might add the functionality to send a task to iCal for a reminder. They will also be able to be marked as “in progress” so you can see what has been started, but not yet finished.</p>
<p>Local storage will take place in a file in the <em>Application Support</em> folder for the app. This means there is only one central task repository that’s not easily accessible by the user. Because of this I will look into exporting tasks into various formats later on so it can be backed up, although since Macs have Time Machine, losing data shouldn’t be a big issue.</p>
<p>Now, this is getting further down the line, but eventually I would like to be able to sync with iCloud, which will then sync with an iPhone/iPad version of the app. Once I have the basics of the Mac app in place, it should be fairly easy to port to iOS and iCloud storage is the preferred method of synching for that. That also covers backing up the data, which is good, but introduces complexity when it comes to ensuring data integrity.</p>
<p>For looks, I’ll try and follow the general look of the Mail.app for Macs. The left-hand side will be the hierarchical group view, and the right will be list of the tasks for that group. I want to keep it fairly simple, so tasks will not have “detail views” at all: they’ll just be descriptions, optional dates, and marked for their various stages of progress.</p>
<p>So, I’ve already started programming this app and within five minutes bumped up against my first issue: getting the NSOutlineView (the hierarchical “group” sidebar) to display data. Next post will explain (amongst other things) what exactly the issue was, and how to use the OutlineView.</p>
]]></content:encoded>
			<wfw:commentRss>http://benreimers.net.au/blog/whats-next-a-first-project/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>On web and software development</title>
		<link>http://benreimers.net.au/blog/on-web-and-software-development</link>
		<comments>http://benreimers.net.au/blog/on-web-and-software-development#comments</comments>
		<pubDate>Wed, 18 Jan 2012 02:46:28 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://benreimers.net.au/?p=44</guid>
		<description><![CDATA[It’s been a while since I’ve blogged. There are a few reasons for that, but one of the mains ones is that web development hasn’t really been exciting me much lately. Mainly I think this is because it’s often frustrating, &#8230; <a href="http://benreimers.net.au/blog/on-web-and-software-development">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It’s been a while since I’ve blogged. There are a few reasons for that, but one of the mains ones is that web development hasn’t really been exciting me much lately. Mainly I think this is because it’s often frustrating, both the development itself, but also dealing with clients who don’t know what they want. There’s nothing worse than having a client say “well, you’re the designer” but who then wants to change everything when you do use your best judgement.</p>
<p>The process of web development is also tedious and annoying. Cross-browser and cross-platform compatibility issues take a lot of time away from doing things that are more fun, like designing or coding. Getting a website to look exactly like you designed it in Photoshop is one thing; getting it to look like that in every browser is another.</p>
<p>It’s not fun anymore, which is a shame, but it’s also not totally unexpected.</p>
<p>Anyway, that leads me to here. Anybody who knows me would know I’m a big Apple user, with an iPhone, iPad, and Mac Pro, so it’s only natural that I would want to start creating things that work for them and try to make some money out of it. The natural choice was iPhone/iOS and Mac development.</p>
<p>Over the last few months I’ve been touching up on my existing programming knowledge and then extending that learning Objective-C/Cocoa for the Mac and CocoaTouch for iOS. It’s been a fun process, and it really gets my brain working like it hasn’t for a long time and I can tell my problem-solving and logic skills getting a work out.</p>
<p>I’m now at the point where I can start to put that knowledge to use. That means writing apps. Hopefully even selling them (though I am aware of the success rate of apps on the various app stores).</p>
<p>This also gives me the opportunity to start blogging again as I explore the frameworks that make up the Cocoa/CocoaTouch environments. As an “intermediate” level programmer it can serve as both a record of my progress, but hopefully it will help others who come across the same problems I do.</p>
<p>So, stay tuned while I start on what will hopefully be a nice career change.</p>
<p>In my next post I will describe my first smaller project, and the first problem I’ve butted my ahead against.</p>
]]></content:encoded>
			<wfw:commentRss>http://benreimers.net.au/blog/on-web-and-software-development/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

