<?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>Kickass Labs &#187; Programming</title>
	<atom:link href="http://www.kickasslabs.com/tag/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kickasslabs.com</link>
	<description>We &#9829; code.</description>
	<lastBuildDate>Wed, 28 Dec 2011 16:57:56 +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>Quick Hits: UIActionSheet cancel button strange behaviour</title>
		<link>http://www.kickasslabs.com/2010/07/03/uiactionsheet-cancel-button-strange-behaviour/</link>
		<comments>http://www.kickasslabs.com/2010/07/03/uiactionsheet-cancel-button-strange-behaviour/#comments</comments>
		<pubDate>Sun, 04 Jul 2010 02:41:39 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Quick Hits]]></category>
		<category><![CDATA[objc]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/2010/07/03/uiactionsheet-cancel-button-strange-behaviour/</guid>
		<description><![CDATA[I just got bit by this and fixed it thanks to this StackOverflow post. http://stackoverflow.com/questions/1197746/uiactionsheet-cancel-button-strange-behaviour Long story short, if your launch an action sheet in a view that lives in a UITabBarController, the &#8220;hit&#8221; box for the cancel button gets &#8230; <a href="http://www.kickasslabs.com/2010/07/03/uiactionsheet-cancel-button-strange-behaviour/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I just got bit by this and fixed it thanks to this StackOverflow post.</p>
<p><a href="http://stackoverflow.com/questions/1197746/uiactionsheet-cancel-button-strange-behaviour" target="_blank">http://stackoverflow.com/questions/1197746/uiactionsheet-cancel-button-strange-behaviour</a></p>
<p>Long story short, if your launch an action sheet in a view that lives in a UITabBarController, the &#8220;hit&#8221; box for the cancel button gets shifted in a VERY STUPID WAY!</p>
<p>The solution is to reference the view you&#8217;re displaying in by the UITabBarController like this:</p>
<pre><code>[sheet showInView:self.parentViewController.tabBarController.view];</code></pre>
<p>Freaking WOW!  Thanks a heap, Apple!</p>
<p>*grumble grumble*</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2010%2F07%2F03%2Fuiactionsheet-cancel-button-strange-behaviour%2F&amp;title=Quick%20Hits%3A%20UIActionSheet%20cancel%20button%20strange%20behaviour" id="wpa2a_2"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2010/07/03/uiactionsheet-cancel-button-strange-behaviour/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The 5 stages of 3.3.1</title>
		<link>http://www.kickasslabs.com/2010/04/11/the-5-stages-of-3-3-1/</link>
		<comments>http://www.kickasslabs.com/2010/04/11/the-5-stages-of-3-3-1/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 04:32:36 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[MonoTouch]]></category>
		<category><![CDATA[331]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=449</guid>
		<description><![CDATA[Developers have been up in arms on the news broken by Daring Fireball and TechCrunch.  The reported change in the iPhone developer agreement definitely stops Flash developers from creating iPhone apps using the new tools available CS5, but the sword &#8230; <a href="http://www.kickasslabs.com/2010/04/11/the-5-stages-of-3-3-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Developers have been up in arms on the news broken by <a href="http://daringfireball.net/2010/04/iphone_agreement_bans_flash_compiler" target="_blank">Daring Fireball</a> and <a href="http://techcrunch.com/2010/04/08/adobe-flash-apple-sdk/" target="_blank">TechCrunch</a>.  The reported change in the iPhone developer agreement definitely <a href="http://theflashblog.com/?p=1888" target="_blank">stops Flash developers from creating iPhone apps</a> using the new tools available CS5, but the sword Apple used also cuts into the heart of the <a href="http://monotouch.net/" target="_blank">MonoTouch</a>, <a href="http://www.appcelerator.com/" target="_blank">Appcelerator</a>, <a href="http://unity3d.com/" target="_blank">Unity 3D</a>, <a href="http://anscamobile.com/corona/" target="_blank">Corona</a>, &amp; <a href="http://phonegap.com/" target="_blank">PhoneGap</a> communities.  Being a member of the MonoTouch community, I&#8217;m directly affected by this reported change.  Easily said, I&#8217;ve gone through the <a href="http://en.wikipedia.org/wiki/K%C3%BCbler-Ross_model" target="_blank">5 stages of grief</a> over the news:</p>
<p><span id="more-449"></span></p>
<h3>1] Denial</h3>
<p>It doesn&#8217;t really say that, does it?  I mean, they  must not realize what this will do to other projects not related to Adobe.  I&#8217;m sure they won&#8217;t enforce it.</p>
<h3>2] Anger</h3>
<p>Are you F*%#ING SERIOUS RIGHT NOW!?  Don&#8217;t they realize that some EA games use Lua!?  Are they going take those apps out of the store?  Don&#8217;t give me that &#8220;quality of apps&#8221; crap!  There are TONS of horrible apps written in native Objective-C!  &#8220;<a href="http://www.taoeffect.com/blog/2010/04/steve-jobs-response-on-section-3-3-1/" target="_blank">Crappy devs will make crappy apps regardless of how many layers there are &amp; it doesn’t make sense to limit source-to-source conversion</a>.&#8221;  This is creativity stifling!  Apple&#8217;s going to lose so many apps they&#8217;ll repeal this decision with the QUICKNESS!  I&#8217;m just going to bang out the best apps ever and we&#8217;ll see if Apple tries to take them out of the store.  I DOUBT THEY WILL!  What happened to the approval process!?  Shouldn&#8217;t that be enough!?  Don&#8217;t they understand how error prone manual memory management is!?  FURY!!!</p>
<h3>3] Bargaining</h3>
<p>Maybe we can team up with other developers and convince Apple to change this.  We can show them of the talent that&#8217;ll jump ship.  I mean, we&#8217;re not like those &#8220;sexy app&#8221; guys, right?</p>
<h3>4] Depression</h3>
<p>It&#8217;s over man!  It&#8217;s GAME OVER! Damn it!  I wasted all this time! What will become of my projects!?  I&#8217;m tossing out my iPhone &amp; I&#8217;m definitely not buying an iPad now.  It&#8217;ll just be too painful of a reminder that my app is available on it**.  Nothing to see here except a teary-eyed developer <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<h3>5] Acceptance</h3>
<p>This sucks likes crazy, but I&#8217;ve still got time.  I&#8217;ll make updates to <a href="http://www.touchplaybook.com" target="_blank">Touch Playbook</a> for as long as I can.  MonoTouch is talking about giving developers the ability to create Droid apps and that will kick ass!  Windows Phone 7 is right around the corner and since my app is already written in C#, the port should be very easy.  The HP Slate runs Windows 7 and obviously Silverlight so there&#8217;s another port right there.  I&#8217;ll get started on that this weekend!  If it wasn&#8217;t for MonoTouch, I wouldn&#8217;t have gotten as far along as I did with Touch Playbook.  I don&#8217;t regret a moment.</p>
<h3>Conclusion</h3>
<p>I don&#8217;t know what the future of MonoTouch and iPhone development is.  Rather, I don&#8217;t want to admit what I fear the future is.  I&#8217;d love for a miracle to take place where the reported language is altered in 3.3.1 to allow MonoTouch and other quality iPhone development solutions.  However, if that doesn&#8217;t happen, MonoTouch still definitely rocks!  For the time being, it feels good to be in the final stage.  I don&#8217;t like being so angsty. <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Update</h3>
<p>I do, however, remain hopeful.  I&#8217;ve signed the developer driven Tiny Petition <a href="http://tinypetition.com/NoBanFromTOSChange" target="_blank">against Apple&#8217;s reported TOS change and you can too</a>.  You might ask &#8220;Abel, isn&#8217;t this the barganing step?  Did you relapse?&#8221; and I would reply &#8220;Not exactly&#8221;.  In the bargaining step my thoughts came from desperation in the wake of anger.  Right now, signing the petition springs from hope and a desire to stand with my fellow MonoTouch devs and other devs effected by this.  This time the motivation is less about me and more about the community.</p>
<p>**I&#8217;ve already taken a stab at learning Objective-C and would rather use my time on other languages.  I don&#8217;t see myself taking up the effort again.  Life&#8217;s too short and I really like languages like C# &amp; Ruby.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2010%2F04%2F11%2Fthe-5-stages-of-3-3-1%2F&amp;title=The%205%20stages%20of%203.3.1" id="wpa2a_4"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2010/04/11/the-5-stages-of-3-3-1/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>I LOVE MonoTouch</title>
		<link>http://www.kickasslabs.com/2010/01/24/i-love-monotouch/</link>
		<comments>http://www.kickasslabs.com/2010/01/24/i-love-monotouch/#comments</comments>
		<pubDate>Sun, 24 Jan 2010 22:42:47 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[MonoTouch]]></category>
		<category><![CDATA[noob]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=415</guid>
		<description><![CDATA[Don't get me wrong, XCode is great...in it's own way...but as a .Net dev coming to the iPhone platform, MonoTouch rocks my world!
For the other devs in my shoes looking to play with MonoTouch, here are some things to keep in mind: <a href="http://www.kickasslabs.com/2010/01/24/i-love-monotouch/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Don&#8217;t get me wrong, XCode is great&#8230;in it&#8217;s own way&#8230;but as a .Net dev coming to the iPhone platform, <a href="http://monotouch.net/" target="_blank">MonoTouch</a> rocks my world!</p>
<p>For the other devs in my shoes looking to play with <a href="http://monotouch.net/" target="_blank">MonoTouch</a>, here are some things to keep in mind:<span id="more-415"></span></p>
<ul>
<li>If you want to subclass something like UIView, UIImageView, or any class that&#8217;s originally an Objective-C class &amp; use your new class in your  XIB, you need to&#8230;
<ul>
<li>Make sure your constructor includes IntPtr constructor.</li>
<li>Sometimes you&#8217;ll need to register your classes like this:
<pre>[MonoTouch.Foundation.Register("MyAwesomeView")]
public class MyAwesomeView : UIView
{
   public MyAwesomeView (IntPtr handle) : base(handle)
   {
      Initialize ();
   }
   //My awesome code here!
}
</pre>
</li>
<li>If you simply type in the name of your custom subclassed view into IB without declaring it in code first, sometimes you get a &#8220;partial class&#8221; in the view controller&#8217;s xib code-behind file (MySensationalViewController.xib.designer.cs).  If that happens, you <strong>DON&#8217;T</strong> need to register your class, but you <strong>DO</strong> need to set your class definition to &#8216;partial&#8217;.  Here&#8217;s an example:
<pre>public partial class MyFantasticView : UIView
{
   public MyFantasticView  (IntPtr handle) : base(handle)
   {
      Initialize ();
   }
   //Your awesome code here!
}</pre>
</li>
</ul>
</li>
<li>Much like Visual Studio, you get awesome debugging tools so make sure to get familiar with &#8220;watches&#8221; (While at  break point: View -&gt; Debug Windows -&gt; Watch) and the &#8220;Expression Evaluator&#8221; (While at  break point: Run -&gt; Expression Evaluator).</li>
<li>There are also helpful tools such as a &#8220;Reg-Ex Toolkit&#8221; and an &#8220;Add-in&#8221; manager that can be hooked into repositories for even more functionality&#8230;as more repositories become available <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<p>When you have a friendly, yet powerful IDE to work with, developing software becomes enjoyable.  I&#8217;ll definitely be using this IDE to create my first iPhone app submission to the AppStore.  As I learn more about MonoTouch, I&#8217;ll make sure to post my findings here.  In the meanwhile, those of you looking to get more info about MonoTouch should checkout <a href="http://monotouch.net/" target="_blank">its homepage</a>.  The MonoTouch site has a ton of tutorials, documentation, and multiple ways to plug into the MT community.  At a glance, you might scoff at the asking price of $399 for a yearly license, but when you consider how much faster you&#8217;ll be able to put together quality apps, it might be worth it for you.   I know it is for me.</p>
<p>Happy Coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2010/01/24/i-love-monotouch/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Quick Hits: Unit Testing iPhone Apps</title>
		<link>http://www.kickasslabs.com/2009/07/05/quick-hits-unit-testing-iphone-apps/</link>
		<comments>http://www.kickasslabs.com/2009/07/05/quick-hits-unit-testing-iphone-apps/#comments</comments>
		<pubDate>Sun, 05 Jul 2009 19:04:35 +0000</pubDate>
		<dc:creator>Brad</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[objc]]></category>
		<category><![CDATA[tdd]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=381</guid>
		<description><![CDATA[I have a few things to add to the woefully incomplete official documentation on setting up automated tests in your iPhone apps: You need to add your main application executable target as a direct dependency of the test target, so &#8230; <a href="http://www.kickasslabs.com/2009/07/05/quick-hits-unit-testing-iphone-apps/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I have a few things to add to the woefully incomplete <a href="http://developer.apple.com/IPhone/library/documentation/Xcode/Conceptual/iphone_development/135-Unit_Testing_Applications/unit_testing_applications.html" title="iPhone Development Guide: Unit Testing Applications" target="iphonetestdocs">official documentation on setting up automated tests in your iPhone apps</a>:</p>
<ol>
<li>You need to add your main application executable target as a direct dependency of the test target, so that you&#8217;re always testing against your latest build.  Do this by double-clicking on the test target, going to the &#8220;General&#8221; pane in the properties dialog, and adding your app under &#8220;Direct Dependencies&#8221;.  (This was actually mentioned in the OCUnit tutorial for Cocoa, but not the one about iPhone testing.)</li>
<li>Your linker needs to know about the objects you&#8217;re testing.  An easy way to do this is to add the .m files for those classes to the &#8220;Compile Sources&#8221; group in your test target.  You&#8217;ll also have to make sure you link against any frameworks used by these objects.  (You could also tell your app target to export all symbols, then link your test target to it as you would a library.) (Thanks to Chris Hanson for pointing out this procedural improvement in comments.) <del datetime="2009-07-06T02:48:59+00:00">You need to explicitly link the object files of the classes you&#8217;re testing.  These are the &#8220;.o&#8221; files in your build folder.  To do this: Double-click on the test target, go to the &#8220;General&#8221; pane, add a new item under &#8220;Linked Libraries&#8221;.  In the dialog that pops up, choose &#8220;Add Other&#8230;&#8221; and add your class&#8217;s .o file.</del></li>
<li>When you run your tests, one failure looks like two:  Failed tests show up in Xcode as errors (just like compile errors, &#038;c). Any test failure triggers a second error, and you&#8217;ll see something like &#8220;Failed tests for architecture &#8216;i386&#8242; (GC OFF)&#8221;. The docs never say so, but this appears to be normal.  Fix the failing test, and it goes away.</li>
</ol>
<p>Anything else to add?  Drop us a comment!</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2009%2F07%2F05%2Fquick-hits-unit-testing-iphone-apps%2F&amp;title=Quick%20Hits%3A%20Unit%20Testing%20iPhone%20Apps" id="wpa2a_6"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2009/07/05/quick-hits-unit-testing-iphone-apps/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>UINavigationController Tricks</title>
		<link>http://www.kickasslabs.com/2009/07/03/uinavigationcontroller-tricks/</link>
		<comments>http://www.kickasslabs.com/2009/07/03/uinavigationcontroller-tricks/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 22:39:03 +0000</pubDate>
		<dc:creator>Brad</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[objc]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=366</guid>
		<description><![CDATA[For an iPhone UI I&#8217;m developing, I need to have one UINavigationController nested inside another, and to have the inner UINavigationController&#8217;s events push a view on to the outer one&#8217;s stack. CocoaTouch didn&#8217;t give this to me for free, but &#8230; <a href="http://www.kickasslabs.com/2009/07/03/uinavigationcontroller-tricks/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For an iPhone UI I&#8217;m developing, I need to have one UINavigationController nested inside another, and to have the inner UINavigationController&#8217;s events push a view on to the outer one&#8217;s stack.  CocoaTouch didn&#8217;t give this to me for free, but there <i>was</i> a simple solution.</p>
<p>This post assumes that you&#8217;re familiar with the fundamentals of iPhone programming, including view controllers, UINavigationController, and delegates.  There is <a href="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2009/07/navtest.tgz" title="UINavigationController Tricks sample code">sample code for this post</a>, which is released under version 2 of the <a href="http://sam.zoy.org/wtfpl/" title="WTFPL">WTFPL</a>.  </p>
<p><b>The Problem</b></p>
<p>I&#8217;m working on a multi-step UI for a game.  Expressing these steps as a regular drill-down table-style UI on the iPhone felt cumbersome, and games can&#8217;t afford for processes to feel cumbersome; people will stop playing.  One solution that occurred to me was batching related sets of steps in a smaller navigation table &#8211; so in Step 1 you&#8217;d drill through substeps 1A, 1B, and 1C before moving to Step 2.  The fact that the whole view wouldn&#8217;t be replaced with every choice seemed like it would be less destructive of the user&#8217;s mental context, and the chunking of substeps should make it easier for the users to wrap their heads around the process.  (No word yet on whether this solves my UI problem, but I like it so far.)</p>
<p>My UI solution contained its own technical problem, though: If I&#8217;m expressing the process steps in a UINavigationController, and expressing the substeps in a nested UINavigationController, how does the inner navigation controller notify the outer one that the user&#8217;s last substep choice completes that step and it&#8217;s time to move to the next step &#8211; or in programmatic terms, how does the inner UINavigationController tell the outer one to push a new view onto the outer one&#8217;s stack?</p>
<p>Or, putting it more visually, how do I get from here:</p>
<p><img src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2009/07/navcontricks1.png" alt="navcontricks1" title="navcontricks1" width="414" height="770" class="aligncenter size-full wp-image-373" /></p>
<p>&#8230;to here:</p>
<p><img src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2009/07/navcontricks2.png" alt="navcontricks2" title="navcontricks2" width="414" height="770" class="aligncenter size-full wp-image-374" /></p>
<p>In the non-nested situation when you wanted to push a new view onto a UINavigationController&#8217;s stack, you&#8217;d do the following in the current view:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>self.navigationController pushViewController<span style="color: #002200;">:</span>nextViewController animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>So in my nested case, I need to do that, but pushing onto the outer navigation controller&#8217;s stack from a view controller on the inner navigation controller&#8217;s stack.  I tried a number of naive (but sensible-seeming) targets for the pushViewController:animated: action, such as:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">self.navigationController.navigationController
self.navigationController.parentViewController.navigationController</pre></div></div>

<p>Nothing worked.  I set a breakpoint and drilled down through the members of self.navigationController, and no path to that outer UINavigationController was apparent.</p>
<p><b>The Solution</b></p>
<p>While investigating the innards of UINavigationController, I stumbled upon a writable property that looked like it might help: The delegate.  When creating the inner UINavigationController, I added one line of code:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">innerNavCntlr.delegate <span style="color: #002200;">=</span> self; <span style="color: #11740a; font-style: italic;">// THIS IS THE MAGIC, PART 1</span></pre></div></div>

<p>Keep in mind that this is called in the view controller on top of the outer navigation controller&#8217;s stack, so &#8220;self&#8221; has access to the outer navigation controller.</p>
<p>When the view on top of my inner navigation controller&#8217;s stack is ready to signal the outer navigation controller, I do the following:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// THIS IS THE MAGIC PART 2</span>
UIViewController <span style="color: #002200;">*</span>topVC <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>UIViewController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>self.navigationController.delegate;
<span style="color: #002200;">&#91;</span>topVC.navigationController pushViewController<span style="color: #002200;">:</span>nextCntlr animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>A couple of notes:  First, the view controller that creates the inner UINavigationController must implement UINavigationControllerDelegate, or you&#8217;ll get a compiler warning &#8211; but you can just declare that it does so in the header file, as none of the methods in that interface are required.</p>
<p>Secondly: If you&#8217;re like me, this feels like an abuse of the delegate property.  Now there&#8217;s no reason that you couldn&#8217;t actually use that object productively as the inner navigation controller&#8217;s delegate &#8211; I just haven&#8217;t done so here.  And the fact that the delegate property has to be casted to be used this way says to me that it wasn&#8217;t meant for this &#8211; explicit casts are always a code smell.  (Anal-retentive types might want to put in some type-checking around that cast for safety.)</p>
<p>That said, it works, and I haven&#8217;t run into a maintainability problem yet, as this code doesn&#8217;t really get re-used in many places.  Were I expecting to use this trick often, I might package up a subclass of UINavigationController (call it NestedNavigationController) that actually took an outer UIViewController or UINavigationController property.  Then again I&#8217;m finding that in Cocoa, subclassing is often a code smell&#8230;</p>
<p>Got a better solution?  I&#8217;m interested &#8211; please leave a comment below!</p>
<p><b>Update:</b>  Whoops.  Comments are enabled now.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2009%2F07%2F03%2Fuinavigationcontroller-tricks%2F&amp;title=UINavigationController%20Tricks" id="wpa2a_8"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2009/07/03/uinavigationcontroller-tricks/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Quick and Dirty Messaging</title>
		<link>http://www.kickasslabs.com/2008/11/22/93/</link>
		<comments>http://www.kickasslabs.com/2008/11/22/93/#comments</comments>
		<pubDate>Sat, 22 Nov 2008 20:05:55 +0000</pubDate>
		<dc:creator>Brad</dc:creator>
				<category><![CDATA[Great Minds]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[gm]]></category>
		<category><![CDATA[message queue]]></category>
		<category><![CDATA[messaging]]></category>
		<category><![CDATA[rails rumble]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[rumble]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=93</guid>
		<description><![CDATA[Our Rails Rumble 2008 entry, Great Minds (you can have a look at the latest version or the original Rumble version), required a messaging system. Such systems are easy to do wrong, and we knew we&#8217;d need something that would &#8230; <a href="http://www.kickasslabs.com/2008/11/22/93/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Our <a href="http://railsrumble.com/" title="Rails Rumble 2008" target="rr2008">Rails Rumble 2008</a> entry, <i>Great Minds</i> (you can have a look at the <a href="http://greatminds.kickasslabs.com/" title="Great Minds" target="gmkal">latest version</a> or the <a href="http://greatminds.r08.railsrumble.com/" title="Great Minds - Rumble Version" target="gmrr">original Rumble version</a>), required a messaging system.  Such systems are easy to do wrong, and we knew we&#8217;d need something that would stay solid under unknown load during Rumble judging.</p>
<p>The solution was quick &amp; dirty (as most solutions are during Rails Rumble), but the results worked, and allowed us to qualify for judging and reach a respectable 28th place finish in the &#8220;Completeness&#8221; category.</p>
<p>Check out the details after the fold.</p>
<p><span id="more-93"></span></p>
<h3>Design Constraints</h3>
<p><i>Great Minds</i> is a word game played by 2 or more players.  The game is played in a virtual chat <b>Room</b>, containing one or more <b>Players.</b>  Players can take various actions, such as submitting a word to the game, chatting, or changing their handle/username.  The results of these actions must be transmitted to other players in the room.</p>
<p>Other constraints on the design included:</p>
<ul>
<li><b>No New Technologies:</b>  There are tools like <a href="http://juggernaut.rubyforge.org/" title="Juggernaut" target="juggernaut">Juggernaut</a> that make messaging pretty easy, but we had no hands-on experience with them, and learning a new tool on a 48-hour schedule was deemed a risk to completing the project &#038; qualifying for Rumble judging.</li>
<li><b>Broadcast:</b>  We needed something more than a simple message queue like <a href="http://xph.us/software/beanstalkd/" title="Beanstalk" target="beanstalk">Beanstalk</a>; the consumer of a message couldn&#8217;t remove it from the queue, as there might be other consumers needing the same message.</li>
<li><b>Room State Reconstruction:</b>  Someone coming to the room for the first time (or leaving and returning) should be able to see the current room state, including all participants, recently played words, and recent chat.</li>
<li><b>Replay:</b>  Though we didn&#8217;t get around to implementing it, we wanted to offer the ability to review a particularly funny game.</li>
</ul>
<p>The first two constraints affected our design and technology choices; the second two demanded that the messages be persisted.  (Alternatively, we could have saved the room state in some other way, but as long as we had the messages anyway, it seemed simpler to just keep them and reconstruct the state.)</p>
<h3>Client Implementation</h3>
<p>In the absence of a viable push solution like Juggernaut, we opted for a polling solution:  Clients would periodically send a signal that:</p>
<ul>
<li>let the server know they&#8217;re still alive and connected,</li>
<li>sent any new messages to the server, and</li>
<li>requested any pending messages from the server.</li>
</ul>
<p>On the client side, this meant that every message got packaged as JSON, stuck in a queue, and periodically collected and sent to the server as the optional payload of a keep-alive signal.  With some help from Prototype, this was as simple as:</p>
<pre>
  function SyncMessages() {
          var data = Object.toJSON(MESSAGES_QUEUE);
          var url = '/room/sync_messages';
          var params = {
                  authenticity_token: AUTH_TOKEN,
                  messages: '[]',
                  //messages: Object.toJSON(MESSAGES_QUEUE),
                  last_message_id: LAST_MESSAGE_ID };

          new Ajax.Request(url, {
            method: 'post',
                  parameters: params,
            onSuccess: HandleMessages });
  }

  SyncMessages(); //start first on load
  var message_syncer = new PeriodicalExecuter(SyncMessages, 3);
</pre>
<p><code>HandleMessages()</code> updates the DOM based on messages coming back.</p>
<p>The other feature to note is the <code>LAST_MESSAGE_ID</code> token above.  Each client is responsible for keeping track of the last message ID it got.  On the server side, message IDs are assigned sequentially, so all new messages are guaranteed to have a higher ID.</p>
<p>We could have kept track of each client&#8217;s last message on the server side, but this would have been much more complex &#8211; we would have needed to store data either in the session (which already held a fair amount of stuff) or in another table in order to keep track of who had received what.</p>
<h3>Server Implementation</h3>
<p>On the server side, messages were persisted in a table.  This table would have relatively frequent inserts, somewhat more frequent reads, and no updates or deletions.  For this reason, we went with the default MyISAM table architecture.  (We had considered a design that would have updated the table with delivery status information and would have required InnoDB&#8217;s row-level locking, but in the end we opted for the simpler design.)  The table looks like:</p>
<pre>
  class CreateMessages < ActiveRecord::Migration
    def self.up
      create_table :messages do |t|
        t.integer :message_type_id, :room_id, :game_id, :user_id
        t.string  :data, :user_handle
        t.timestamps
      end
    end

    def self.down
      drop_table :messages
    end
  end
</pre>
<p>It also has an index:</p>
<pre>
  class AddRoomIndexToMessages < ActiveRecord::Migration
    def self.up
      add_index :messages, [:room_id, :id]
    end

    def self.down
      remove_index :messages, [:room_id, :id]
    end
  end
</pre>
<p>Recall that the client keeps track of the last message it got, and periodically requests all messages since.  This index speeds that request - which is just <code>msgs = Message.find :all, :conditions => ['room_id = ? AND id > ?', session['room_id'], last_message_id], <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder => 'id'</code>.  (Yes, I know that should be a <a href="http://ryandaigle.com/articles/2008/8/20/named-scope-it-s-not-just-for-conditions-ya-know" title="Named Scopes" title="namedscopes">named scope</a>.  I hadn't gotten around to learning those yet at the time of the Rumble.)</p>
<p>When the a keep-alive signal hits the server:</p>
<ul>
<li>any new messages attached to the signal are added to the <code>messages</code> table,</li>
<li>any game mechanics related to those messages are executed (which may result in more messages being added to the table), and</li>
<li>all messages for the caller's room with an ID greater than the caller's LAST_MESSAGE_ID are packaged as JSON and sent back down in the HTTP response.</li>
</ul>
<p>A note:  If you're in a room and you enter (for example) a chat message, there's actually a server round-trip involved (pushing the message to the server and getting the same message back as a response) before that chat message is shown in your browser.  We worried about this, but not for long - the interactivity delay turned out to be minimal, and it was much simpler to keep it this way (every message is treated the same for all clients) than to create an exception (you update your DOM with your chat messages immediately, but your own chat messages are somehow filtered from your message stream).</p>
<h3>What's Missing?</h3>
<p>Obviously, this was a quick &amp; dirty solution, tailored to the immediate needs of a Rails Rumble project.  Here's what I'd do differently (and indeed, will do differently, as we have plans for the future of Great Minds - stay tuned):</p>
<ul>
<li><b>Security:</b>  We do use the Rails session <code>authenticity_token</code>, but there's still no protection from a server flood from someone who has a token, either by cranking down the polling interval or by fiddling with the LAST_MESSAGE_ID.</li>
<li><b>Server Push:</b>  Polling is wasteful - requests are made whether or not there are any messages to send or receive.  We plan to move to Juggernaut soon.</li>
<li><b>Decoupling from Game Mechanics:</b>  In the first iteration, message receipt and delivery were too intimately tied to game mechanics, with <code>Message</code> objects being explictly constructed and followed by <code>Message.save!</code> calls.  I've already started the process of teasing them apart in preparation for the move to Juggernaut, factoring this into a <code>deliver_message()</code> method.</li>
</ul>
<p>Questions?  Thoughts?  Add a comment!  I promise to get back to you.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2008%2F11%2F22%2F93%2F&amp;title=Quick%20and%20Dirty%20Messaging" id="wpa2a_10"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2008/11/22/93/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

