<?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>Inside RogueSheep &#187; Cocoa</title>
	<atom:link href="http://blog.roguesheep.com/category/cocoa/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.roguesheep.com</link>
	<description>Behind the scenes with the sheep</description>
	<lastBuildDate>Thu, 15 Jul 2010 20:17:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Acorn and JSTalk</title>
		<link>http://blog.roguesheep.com/2010/03/27/acorn-and-jstalk/</link>
		<comments>http://blog.roguesheep.com/2010/03/27/acorn-and-jstalk/#comments</comments>
		<pubDate>Sat, 27 Mar 2010 21:25:52 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Macintosh]]></category>
		<category><![CDATA[Postage]]></category>

		<guid isPermaLink="false">http://blog.roguesheep.com/?p=357</guid>
		<description><![CDATA[Last month when planning for exhibiting our iPhone apps at Macworld Expo, we decided to use the fabulous services at MOO to create promotional materials to hand out at the show. We wanted to have a a simple way for attendees to take something with them with as a reminder of our iPhone apps. We [...]]]></description>
			<content:encoded><![CDATA[<p>Last month when planning for exhibiting <a href="http://apps.roguesheep.com/">our iPhone apps</a> at Macworld Expo, we decided to use the fabulous services at <a href="http://us.moo.com/en/">MOO</a> to create promotional materials to hand out at the show. We wanted to have a a simple way for attendees to take something with them with as a reminder of our iPhone apps. We also needed a method to hand out iTunes App Store promotional codes that could be used to redeem copies after the attendees went home.</p>

<p>Moo&#8217;s MiniCards were very affordable and sized just right for our purposes: 
</p>

<div style="text-align:center;"><img src="http://blog.roguesheep.com/wp-content/uploads/2010/03/Macworld-MooCards-Blog.png" alt="Macworld MooCards Blog.png" border="0" width="400" height="198" /></div>

<p>They are sized small enough that its not a burden to carry around the conference. Not everyone at Macworld wants to load up a bag full of chotskies, schwag and product materials! We found the MiniCard&#8217;s appearance and quality really attracted the attention of attendees. Also, critical to our needs each card can have one side that con be printed with a separate image. Perfect for making individual cards each have a unique promo code. 
</p>

<p>Apple allots developers 50 promotional codes per version of their application. In total we had four versions of Postage plus, SnoGlobe and RoseGlobe that we wanted to make a full set of 50 moo cards with a promo code on the back for. That was <strong>300</strong> unique images we needed to make and upload! Certainly a tedious process at best.</p>

<p>Lucky for us, we had some automation magic in our toolchest thanks to Flying Meat&#8217;s image editor <a href="http://flyingmeat.com/acorn/">Acorn</a> and <a href="http://shapeof.com/">Gus&#8217;s</a> excellent new technology project <a href="http://jstalk.org/">JSTalk</a>. While there are plenty of Mac OS graphics tools that support AppleScript for automation, I have to be completely honest here. Every time I try to use AppleScript I find myself struggling with the syntax and terminology. Frequently I just give up and do whatever I was trying to accomplish manually after banging my head on the keyboard for a few hours.</p>

<p>JSTalk exposes Cocoa frameworks and applications for scripting and automation using JavaScript. It also performs some preprocessor shenanigans so you can write JavaScript that looks a lot like Objective-C. Being an Objective-C programmer for a good number of years now, I find this absolutely charming. I don&#8217;t have to bootstrap myself into learning a new language, especially not some crazy english-language hybrid that demoralizes me for weeks at time after it beats me over the head with my apparent lack of basic English language literacy.</p>

<p>While Acorn has built-in support for JSTalk, Gus has made it easy for other applications to add support as well. JSTalk also allows other applications without support to be automated using the Script Bridge.</p>

<p>To create the backs for our MiniCards, we started with a the image of the layout of the back of the card. Brad left an empty spot for the text :
</p>

<div style="text-align:center;"><img src="http://blog.roguesheep.com/wp-content/uploads/2010/03/PostageMooCardsBack.png" alt="PostageMooCardsBack.png" border="0" width="437" height="189" /></div>

<p>Then I created a JSTalk script to drive Acorn. First the script reads in the promo codes from the file that iTunes Connect creates for you when you generate promo codes. Then for each of the codes, the script opens our layout image, creates a new text layer with the promo code and styles it properly. Finally, it saves the newly created image with a proper name.</p>

<p>Here is what the script looks like :</p>

<div class="codecolorer-container objc blackboard codecolorer-noborder" style="border:1px solid #9F9F9F;width:435px;"><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">var acorn <span style="color: #002200;">=</span> JSTalk.application<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">&quot;Acorn&quot;</span><span style="color: #002200;">&#41;</span>;<br />
<br />
var codes <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithContentsOfFile<span style="color: #002200;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;/Users/twenty3/Desktop/SnoGlobePromoCodes.txt&quot;</span><span style="color: #002200;">&#93;</span>;<br />
var lines <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>codes componentsSeparatedByCharactersInSet<span style="color: #002200;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSCharacterSet_Class/"><span style="color: #400080;">NSCharacterSet</span></a> newlineCharacterSet<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;<br />
<br />
var sourceFilePath <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">&quot;/Users/twenty3/Desktop/&quot;</span><br />
var sourceFileName <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">&quot;SnoGlobeMooCardsBack&quot;</span>;<br />
var sourceFileExtension <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">&quot;.png&quot;</span>;<br />
var destinationFolder <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">&quot;SnoGlobeMooBacks/&quot;</span>;<br />
<br />
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>i<span style="color: #002200;">=</span><span style="color: #2400d9;">0</span>; i&lt;<span style="color: #002200;">&#91;</span>lines length<span style="color: #002200;">&#93;</span>; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span><br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; var doc <span style="color: #002200;">=</span> acorn.open<span style="color: #002200;">&#40;</span>sourceFilePath<span style="color: #002200;">+</span>sourceFileName<span style="color: #002200;">+</span>sourceFileExtension<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; var layer <span style="color: #002200;">=</span> doc.layers<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; var wc <span style="color: #002200;">=</span> doc.windowController<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; var shapeLayer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>wc addNewShapeLayer<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; var textArea <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>shapeLayer addTextWithBounds<span style="color: #002200;">:</span>NSMakeRect<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">526</span>, <span style="color: #2400d9;">106</span>, <span style="color: #2400d9;">264</span>, <span style="color: #2400d9;">40</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; var promoCodeText &nbsp; <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableAttributedString_Class/"><span style="color: #400080;">NSMutableAttributedString</span></a> alloc<span style="color: #002200;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; initWithString<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>lines objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; var promoCodeFont &nbsp; <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSFont_Class/"><span style="color: #400080;">NSFont</span></a> fontWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Menlo-Bold&quot;</span> size<span style="color: #002200;">:</span><span style="color: #2400d9;">30</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; var promoCodeColor&nbsp; <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSColor_Class/"><span style="color: #400080;">NSColor</span></a> whiteColor<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; var promoStyle&nbsp; &nbsp; &nbsp; <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSMutableParagraphStyle_Class/"><span style="color: #400080;">NSMutableParagraphStyle</span></a> defaultParagraphStyle<span style="color: #002200;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mutableCopyWithZone<span style="color: #002200;">:</span>NSDefaultMallocZone<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; promoStyle.setAlignment<span style="color: #002200;">&#40;</span>NSCenterTextAlignment<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; var promoCodeAttributes <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; promoCodeFont, NSFontAttributeName,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; promoCodeColor, NSForegroundColorAttributeName,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">nil</span> <span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>promoCodeText setAttributes<span style="color: #002200;">:</span>promoCodeAttributes<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; range<span style="color: #002200;">:</span>NSMakeRange<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0</span>,<span style="color: #002200;">&#91;</span>promoCodeText length<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>textArea setContents<span style="color: #002200;">:</span> promoCodeText<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; doc.dataOfType<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">&quot;public.png&quot;</span><span style="color: #002200;">&#41;</span>.writeToFile<span style="color: #002200;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sourceFilePath <span style="color: #002200;">+</span> destinationFolder <span style="color: #002200;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sourceFileName <span style="color: #002200;">+</span> i <span style="color: #002200;">+</span> sourceFileExtension <span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; doc.close<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">&#91;</span>acorn activate<span style="color: #002200;">&#93;</span>;</div></div>

<p>Now, I got a little bi-polar there going back and forth between Objective-C style brackets and plain ol&#8217; JavaScript style function calls. You can use whatever syntax makes the most sense to you personally though. </p>

<p>And here is a sample of one of the generated images:</p>

<div style="text-align:center;"><img src="http://blog.roguesheep.com/wp-content/uploads/2010/03/PostageMooCardsBack0.png" alt="PostageMooCardsBack0.png" border="0" width="437" height="189" /></div>

<p>Using this technique we generated all 300 images in something like 10 minutes. Add a little time to that to create the script and it added up to a whole lot of time saved. Plus, it was way more fun than the copy/paste dance it would have taken to do this by hand. </p>

<p>Count me in as a fan of <a href="http://jstalk.org/">JSTalk</a>. Its such a cool technology and Gus has been kind enough to develop and distribute it completely free of charge! If you develop Mac apps you should think about dropping in support for JSTalk. If you have the need to do some automated image manipulation or creation, Acorn + JSTalk may be the perfect tool to tackle your problem. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roguesheep.com/2010/03/27/acorn-and-jstalk/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>iPhone OS 4.0?</title>
		<link>http://blog.roguesheep.com/2010/01/26/iphone-os-4-0/</link>
		<comments>http://blog.roguesheep.com/2010/01/26/iphone-os-4-0/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 03:49:09 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://blog.roguesheep.com/?p=255</guid>
		<description><![CDATA[I know that we are all excited about the mythical Apple tablet materializing tomorrow, but with all the pontification already spread across the far corners of the media, I don&#8217;t feel I have much to add to the story. On the other hand, I have been thinking a bit about iPhone OS 4.0. I don&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>I know that we are all excited about the mythical Apple tablet materializing tomorrow, but with all the pontification already spread across the far corners of the media, I don&#8217;t feel I have much to add to the story. On the other hand, I have been thinking a bit about iPhone OS 4.0. I don&#8217;t think we will hear about 4.0 tomorrow if there really is a tablet. It seems like that would just be too much to unload all at once. (I do allow that we might hear about an incremental update such as iPhone OS 3.2 though). Still, we&#8217;ll be all out of things to speculate on after tomorrow, so perhaps we can kickstart the next round now?</p>

<p><strong>User Desire</strong></p>

<p>As a user, my hope for iPhone OS 4.0 is a way for third party developers to provide background media playing applications. I understand why Apple wants to be careful with allowing any ol&#8217; process to be granted the ability to run in the background. Sure&#8230; power users will be able to manage background processes by hand, no problem. As we have seen on the desktop though, ordinary people just don&#8217;t want to be bothered with that level of device tweaking. We have been playing with a few Android devices here at the labs and its clear its pretty easy to start installing apps that quietly add background processes that start to suck down the battery without realizing what you have done.</p>

<p>On the other hand, applications like <a href="http://www.pandora.com/">Pandora</a> on the Android phones are so much better than their iPhone equivalents. Being able to tune in that Pandora radio station and having it play in the background just like the built-in iPod application when you launch another app would change the value of these applications immensely. </p>

<p>My suggestion for how Apple can do this without opening Pandora&#8217;s box (zing!) is to create a media service API that allows third party apps to hand media streams off to the iPod player. So the flow would work something like this:</p>

<p>You launch Pandora and use their UI to navigate their music offerings. You tune in the station that suits your current mood and give a bit of a listen. Under the hood Pandora is playing their stream via this new service API that is using the iPod application to serve up the audio. Now, you get the urge to catch-up on your news and launch NetNewsWire for some tasty RSS. When Pandora&#8217;s process is terminated the music keeps on playing, because it is the iPod application that is playing the audio. Its all Apple code running in the background, managing how much power is consumed just the way Apple wants, certified to the level of quality Apple is comfortable with, but we get audio from other providers. </p>

<p>There are of course some wrinkles to work out. If I launch the iPod app while a background stream is running, what is &#8216;Now Playing&#8217;? Perhaps the iPod application shows an appropriate image indicating the Pandora app is the current offering and allows you to quickly switch to it. One can even imagine a more sophisticated approach where the Pandora app could provide a plugin bundle that hosts its UI inside the iPod app, though I doubt this is appealing to Apple. There also needs to be some interesting mechanism for the iPod application to ask the originating service for the next or previous media file so that mini-controls that can be used to control the iPod in the background work as expected. Perhaps this is solved through a call-back into a simple code-bundle provided by the third party application? I&#8217; m confident though there is some low impact way to achieve Apple&#8217;s goals and still enrich the media-playing experience on the device.</p>

<p><strong>Developer Desire</strong></p>

<p>So that&#8217;s my biggest desire as an iPhone user, but what about as an iPhone developer? What I would love to see next is a basic suite of video editing APIs. The problem with the iPhone OS and video right now is that if you want to do anything to process frames of video you need to have your own code to decode the video and re-encode after you have done your processing. This is not exactly trivial code to do well and open source starting points are potentially fraught with licensing and patent peril.</p>

<p>Even if you roll your own codec, perhaps even getting down and dirty with some ARM assembly, you still can&#8217;t get access to the built-in hardware assist that allows Apple&#8217;s software to capture and encode video at decent performance. The last thing we want to do as an iPhone developer is invest a lot of time in developing a codec for the iPhone and find that the best we can do is H.263 at a miserable frame rate. We also don&#8217;t want to force the user to wait around in our application for an encode to finish. Once again we need some way to hand this off and allow the OS to encode in the background for us so our users are not trapped in our application waiting for their edit to finish.</p>

<p>A basic QuickTime derived API that would allow us to take a video file, access individual frames and provide our own sequence of frames to encode into a new movie would be just the ticket. I realize that the advanced encoders typically have licensing requirements and perhaps Apple&#8217;s current license for their iPhone software doesn&#8217;t allow for this to be opened up. Hopefully it is something that can be addressed in the next version of the OS anyway?</p>

<p>Surely we are in for a interesting ride with the big announcement tomorrow. No doubt the next 6 months will be an interesting one for those of playing with Apple technologies. I suspect WWDC will be chock full of new content this year!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roguesheep.com/2010/01/26/iphone-os-4-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone User Interface Projects</title>
		<link>http://blog.roguesheep.com/2009/12/17/iphone-user-interface-projects/</link>
		<comments>http://blog.roguesheep.com/2009/12/17/iphone-user-interface-projects/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 21:52:22 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Postage]]></category>
		<category><![CDATA[RogueSheep]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://blog.roguesheep.com/?p=195</guid>
		<description><![CDATA[Brad and I have recently contributed a chapter to a new iPhone book focused on user interface design and experience from Apress &#8211; iPhone User Interface Design Projects. 

In our chapter we cover much of the process our team went through to create Postage. Along the way we discuss some of the core concepts and [...]]]></description>
			<content:encoded><![CDATA[<p>Brad and I have recently contributed a chapter to a new iPhone book focused on user interface design and experience from Apress &#8211; <em>iPhone User Interface Design Projects</em>. </p>

<p>In our chapter we cover much of the process our team went through to create Postage. Along the way we discuss some of the core concepts and models we employed while designing the user experience. There are also plenty of useful tips, tricks and small details that go into any great iPhone application.</p>

<p>Here is a sample of one of the figures from the book showing some of the early mock-ups of Postage :</p>

<div style="text-align:center;"><img src="http://blog.roguesheep.com/wp-content/uploads/2009/12/Figure-19.png" alt="Figure 19.png" border="0" width="500" height="240" /></div>

<p>If you are developing iPhone applications you might want to give the book a browse. Several of the other chapters are very interesting as well. My favorite is Jürgen Siebert&#8217;s treatise on fonts. He covers all kinds of great info on type, including a detailed anatomy of letterforms. If you ever wanted to start yourself down the path to claim the title of Font Nerd, his chapter would be a great place to start.</p>

<p></p><p>You can grab the book at <a href="http://www.amazon.com/gp/product/1430223596?ie=UTF8&amp;tag=therogblo-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=1430223596">Amazon</a><img src="http://www.assoc-amazon.com/e/ir?t=therogblo-20&amp;l=as2&amp;o=1&amp;a=1430223596" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> or find it on the shelves of any book retailer with a decent selection of software development books. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roguesheep.com/2009/12/17/iphone-user-interface-projects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Animation Sequence</title>
		<link>http://blog.roguesheep.com/2009/12/11/iphone-animation-sequence/</link>
		<comments>http://blog.roguesheep.com/2009/12/11/iphone-animation-sequence/#comments</comments>
		<pubDate>Fri, 11 Dec 2009 16:04:46 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Postage]]></category>
		<category><![CDATA[RogueSheep]]></category>
		<category><![CDATA[Word Spin]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://blog.roguesheep.com/?p=155</guid>
		<description><![CDATA[When writing Postage and WORD SPIN we encountered the same problem again and again: the need to chain a sequence of animations together. For example, when the user navigates to the next page we first animate away the controls for the current view, switch views, then animate the controls in for the new view. Initially, [...]]]></description>
			<content:encoded><![CDATA[<p>When writing <a href="http://postage.roguesheep.com/">Postage</a> and <a href="http://wordspin.roguesheep.com/">WORD SPIN</a> we encountered the same problem again and again: the need to chain a sequence of animations together. For example, when the user navigates to the next page we first animate away the controls for the current view, switch views, then animate the controls in for the new view. Initially, we set the UIView delegate and then in our specified selector implementation kicked off the next animation which itself would eventually call back into a completion selector, and so on. But it&#8217;s largely the same code over and over, and you either need a bunch of similar looking animationDidStop implementations, or a single implementation that branches based on the animation identifier. For example:</p>

<h3>Old Way</h3>

<pre>

<div class="codecolorer-container objc blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> doMoveFromView1ToView2Animation<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>app beginIgnoringInteractionEvents<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView beginAnimations<span style="color: #002200;">:</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;HideView1Animation&quot;</span> context<span style="color: #002200;">:</span> foo<span style="color: #002200;">&#93;</span>; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDuration<span style="color: #002200;">:</span> kDuration<span style="color: #002200;">&#93;</span>; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDelegate<span style="color: #002200;">:</span> self<span style="color: #002200;">&#93;</span>; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDidStopSelector<span style="color: #002200;">:</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>hideView1AnimationDidStop<span style="color: #002200;">:</span>finished<span style="color: #002200;">:</span>context<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>self hideView1Code<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView commitAnimations<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>hideView1AnimationDidStop<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>animationID <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;finished<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span style="color: #400080;">NSNumber</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>finished <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; context<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>context<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView beginAnimations<span style="color: #002200;">:</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;SwapView1AndView2Animation&quot;</span> context<span style="color: #002200;">:</span> foo<span style="color: #002200;">&#93;</span>; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDuration<span style="color: #002200;">:</span> kDuration<span style="color: #002200;">&#93;</span>; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDelegate<span style="color: #002200;">:</span> self<span style="color: #002200;">&#93;</span>; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDidStopSelector<span style="color: #002200;">:</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>swapView1AndView2AnimationDidStop<span style="color: #002200;">:</span>finished<span style="color: #002200;">:</span>context<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>self swapView1AndView2Code<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView commitAnimations<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>swapView1AndView2AnimationDidStop<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>animationID <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;finished<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span style="color: #400080;">NSNumber</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>finished <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; context<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>context<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView beginAnimations<span style="color: #002200;">:</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;ShowView2Animation&quot;</span> context<span style="color: #002200;">:</span> foo<span style="color: #002200;">&#93;</span>; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDuration<span style="color: #002200;">:</span> kDuration<span style="color: #002200;">&#93;</span>; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDelegate<span style="color: #002200;">:</span> self<span style="color: #002200;">&#93;</span>; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDidStopSelector<span style="color: #002200;">:</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>showView2AnimationDidStop<span style="color: #002200;">:</span>finished<span style="color: #002200;">:</span>context<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>self showView2Code<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView commitAnimations<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>showView2AnimationDidStop<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>animationID<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;finished<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span style="color: #400080;">NSNumber</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>finished <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; context<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>context<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>app endIgnoringInteractionEvents<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>self doStuff<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span></div></div>

</pre>

<p>When we embarked on <a href="http://wordspin.roguesheep.com/">WORD SPIN</a> it was time to build something to help tackle this problem. I settled on the concept of sequences, where each individual animation is a step in the overall animation sequence. For the user example of moving from one page to the next in Postage, the new code looks like this:</p>

<h3>New Way</h3>

<pre>

<div class="codecolorer-container objc blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> doMoveFromView1ToView2Animation<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a><span style="color: #002200;">*</span> steps <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> array<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>steps addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>RSViewAnimationSequenceStep stepWithTarget<span style="color: #002200;">:</span> self <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;selector<span style="color: #002200;">:</span> <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>hideView1Code<span style="color: #002200;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;duration<span style="color: #002200;">:</span> kDuration<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>steps addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>RSViewAnimationSequenceStep stepWithTarget<span style="color: #002200;">:</span> self <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;selector<span style="color: #002200;">:</span> <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>swapView1AndView2Code<span style="color: #002200;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;duration<span style="color: #002200;">:</span> kDuration<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>steps addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>RSViewAnimationSequenceStep stepWithTarget<span style="color: #002200;">:</span> self <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;selector<span style="color: #002200;">:</span> <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>showView2Code<span style="color: #002200;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;duration<span style="color: #002200;">:</span> kDuration<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>RSSequenceManager sharedManager<span style="color: #002200;">&#93;</span> invokeSequence<span style="color: #002200;">:</span> steps<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span></div></div>

</pre>

<p>What I really like about this approach is that the entire animation sequence is specified in the same location and it&#8217;s clear how many independent steps there are up front, rather than jumping from one place in the code to the next to see what the whole animation will do. Granted, you could almost achieve the same visual effect by refactoring all the &#8220;beginAnimation&#8221; code into a reusable piece. In fact, that&#8217;s how I started. </p>

<p>The fundamental piece of this paradigm is the sequence step. RSViewAnimationSequenceStep inherits from RSSequenceStep, a base class to define the invocation and delegation of the step. RSViewAnimationSequenceStep is primarily a refactoring of the beginAnimation and commitAnimation boiler plate (I&#8217;ve removed the definition of the helper, init, and dealloc selectors for brevity):</p>

<h3>RSViewAnimationSequenceStep</h3>

<pre>

<div class="codecolorer-container objc blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #a61390;">@interface</span> RSViewAnimationSequenceStep <span style="color: #002200;">:</span> RSSequenceStep <br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">id</span>&nbsp; &nbsp; &nbsp; target_;<br />
&nbsp; &nbsp; <span style="color: #a61390;">SEL</span> &nbsp; &nbsp; selector_;<br />
&nbsp; &nbsp; <span style="color: #a61390;">float</span> &nbsp; duration_;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> stepWithTarget<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> target selector<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">SEL</span><span style="color: #002200;">&#41;</span> selector duration<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">float</span><span style="color: #002200;">&#41;</span> duration;<br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> invoke;<br />
<br />
<span style="color: #a61390;">@end</span><br />
<br />
<span style="color: #a61390;">@implementation</span> RSViewAnimationSequenceStep<br />
<br />
<span style="color: #11740a; font-style: italic;">// helper, init, and dealloc removed for brevity</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> invoke<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView beginAnimations<span style="color: #002200;">:</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;RSViewAnimationSequenceStep&quot;</span> context<span style="color: #002200;">:</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDuration<span style="color: #002200;">:</span> duration_<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDelegate<span style="color: #002200;">:</span> self<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView setAnimationDidStopSelector<span style="color: #002200;">:</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>animationDidStop<span style="color: #002200;">:</span>finished<span style="color: #002200;">:</span>context<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>target_ performSelector<span style="color: #002200;">:</span> selector_<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>UIView commitAnimations<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> animationDidStop<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>animationID <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;finished<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span style="color: #400080;">NSNumber</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>finished <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; context<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>context <br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// delegate is defined in the base class RSSequenceStep (see below)</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>delegate_ stepCompleted<span style="color: #002200;">:</span> self<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #a61390;">@end</span></div></div>

</pre>

<p>The RSSequenceStep is a simple base class to define the general interface:</p>

<h3>RSSequenceStep</h3>

<pre>

<div class="codecolorer-container objc blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #a61390;">@interface</span> RSSequenceStep <span style="color: #002200;">:</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> <br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">id</span>&nbsp; delegate_;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, assign<span style="color: #002200;">&#41;</span> &nbsp; <span style="color: #a61390;">id</span>&nbsp; delegate; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// The object that implements stepCompleted.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> invoke;<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Called to invoke the code necessary for the step. </span><br />
&nbsp; &nbsp; <br />
<span style="color: #a61390;">@end</span><br />
<br />
<span style="color: #a61390;">@interface</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> <span style="color: #002200;">&#40;</span>RSSequenceStepDelegate<span style="color: #002200;">&#41;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> stepCompleted<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span>RSSequenceStep<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> step;<br />
<br />
<span style="color: #a61390;">@end</span></div></div>

</pre>

<p>RSViewAnimationSequenceStep encapsulates handling the beginning and ending of an animation, and then calls back to a delegate when complete. It is a self contained item that can be used independently. If so desired, we could stop here and have client code declare the RSViewAnimationSequenceStep, set the delegate to self, and achieve a large part of the refactoring. But the steps would still be spread apart in the code. That&#8217;s where the RSSequenceManager, and it&#8217;s implementation detail class RSSequence, comes into play, as those two handle chaining the steps together to encapsulate the entire animation.</p>

<h3>RSSequenceManager</h3>

<pre>

<div class="codecolorer-container objc blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #a61390;">@implementation</span> RSSequenceManager<br />
<br />
<span style="color: #11740a; font-style: italic;">// things removed for brevity</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> invokeSequence<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> steps<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; RSSequence<span style="color: #002200;">*</span> sequence <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>RSSequence sequenceWithSteps<span style="color: #002200;">:</span> steps delegate<span style="color: #002200;">:</span> self<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>sequences_ addObject<span style="color: #002200;">:</span> sequence<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#91;</span>sequences_ count<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #2400d9;">1</span> <span style="color: #002200;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#91;</span>sequence invoke<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> sequenceCompleted<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span>RSSequence<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> sequence<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>sequences_ removeObject<span style="color: #002200;">:</span> sequence<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#91;</span>sequences_ 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><br />
&nbsp; &nbsp; <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>sequences_ objectAtIndex<span style="color: #002200;">:</span> <span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span> invoke<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
<span style="color: #002200;">&#125;</span><br />
<span style="color: #a61390;">@end</span></div></div>

</pre>

<p>The bulk of the work, however, happens inside the RSSequence class:</p>

<h3>RSSequence</h3>

<pre>

<div class="codecolorer-container objc blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #a61390;">@interface</span> RSSequence <span style="color: #002200;">:</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> <br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">int</span> &nbsp; &nbsp; &nbsp; &nbsp; currentStepIndex_;<br />
&nbsp; &nbsp; <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a><span style="color: #002200;">*</span>&nbsp; &nbsp; steps_;<br />
&nbsp; &nbsp; <span style="color: #a61390;">id</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delegate_;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> initWithSteps<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> steps delegate<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> delegate;<br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> invoke;<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Called to initiate the sequence. </span><br />
&nbsp; &nbsp; <br />
<span style="color: #a61390;">@end</span><br />
<br />
<span style="color: #a61390;">@interface</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> <span style="color: #002200;">&#40;</span>RSSequenceDelegate<span style="color: #002200;">&#41;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> sequenceCompleted<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span>RSSequence<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> sequence;<br />
<br />
<span style="color: #a61390;">@end</span><br />
<br />
<br />
<span style="color: #a61390;">@implementation</span> RSSequence<br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> initWithSteps<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> steps delegate<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> delegate;<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> self <span style="color: #002200;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; steps_ <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>steps retain<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span> RSSequenceStep<span style="color: #002200;">*</span> step <span style="color: #a61390;">in</span> steps_ <span style="color: #002200;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; step.delegate <span style="color: #002200;">=</span> self;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">return</span> self;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> dealloc<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>steps_ release<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>super dealloc<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> invoke<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIApplication sharedApplication<span style="color: #002200;">&#93;</span> beginIgnoringInteractionEvents<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; currentStepIndex_ <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>self invokeNextStep<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> invokeNextStep<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> currentStepIndex_ <span style="color: #002200;">&amp;</span>lt; <span style="color: #002200;">&#91;</span>steps_ count<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; RSSequenceStep<span style="color: #002200;">*</span> step <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>steps_ objectAtIndex<span style="color: #002200;">:</span> currentStepIndex_<span style="color: #002200;">++</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#91;</span>step invoke<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">else</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIApplication sharedApplication<span style="color: #002200;">&#93;</span> endIgnoringInteractionEvents<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#91;</span>delegate_ sequenceCompleted<span style="color: #002200;">:</span> self<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> stepCompleted<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span>RSSequenceStep<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> step<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>self invokeNextStep<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #a61390;">@end</span></div></div>

</pre>

<p>The sequence manager doesn&#8217;t know or care that a sequence is an animation, and a sequence also doesn&#8217;t know or care what an individual sequence step does. Those classes only assume that a sequence step&#8217;s ending can, but doesn&#8217;t have to, come later than its beginning. Given that, we&#8217;ve also implemented other sequence step subclasses: one that is a simple selector call, one that encapsulates multiple simultaneous steps, and one that handles openGL animations. I&#8217;ve pared the code down a fair bit for this posting, and left out detail &#8212; for example, our view animation step handles delays, custom timing functions, and transitions. But the basic idea is all there. </p>

<p>Lastly, <a href="http://bignerdranch.com/instructors/conway.shtml">Joe Conway</a> over at the <a href="http://bignerdranch.com/">Big Nerd Ranch</a> posted a <a href="http://weblog.bignerdranch.com/?p=215">blog</a> about this problem, and described a solution using a subclass of CALayer that calls completion targets for a given animation key. I like his approach because it theoretically handles all the different kinds of animations, and I&#8217;ll be thinking about how to work his idea into our sequences.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roguesheep.com/2009/12/11/iphone-animation-sequence/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Warning : Love hurts&#8230;</title>
		<link>http://blog.roguesheep.com/2009/11/19/warning-love-hurts/</link>
		<comments>http://blog.roguesheep.com/2009/11/19/warning-love-hurts/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 01:03:09 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Postage]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://blog.roguesheep.com/?p=139</guid>
		<description><![CDATA[Sometimes the ones you love reject you. If you are an iPhone developer this is probably a concept with which you are already intimately familiar. We love developing for the iPhone, but sometimes the App Store and its app review process leaves us feeling a little dejected.

One of our applications was just rejected about halfway [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes the ones you love reject you. If you are an iPhone developer this is probably a concept with which you are already intimately familiar. We love developing for the iPhone, but sometimes the App Store and its app review process leaves us feeling a little dejected.</p>

<p>One of our applications was just rejected about halfway through the review process and it seemed like a unique enough situation that it was worth sharing as a warning to our comrades in the trenches.</p>

<p>Over the past couple of weeks, there have been several reports of iPhone Apps being rejected for use of private APIs. Many of the rejections are from developers that have used the extremely popular <a href="http://github.com/facebook/three20">Three20 library</a> from ex-iPhone developer <a href="http://joehewitt.com/">Joe Hewitt</a>. The developing <a href="http://gizmodo.com/5405978/iphone-apps-have-to-be-approved-by-robots-now-too">consensus</a> is that recently Apple has started using a static code analyzer to flag applications that have used private API calls. </p>

<p>We use a bit of the code from the Three20 library in <a href="http://postage.roguesheep.com/">Postage</a> and caught wind of the <a href="http://groups.google.com/group/three20/msg/9e58113aae30ef53?">issues</a> people had while getting through the review process right before we submitted a new edition of Postage and a couple of related updates. We discovered that even though we didn&#8217;t explicitly use the offending code from the library, it was still being linked into our executable because it was in an Objective-C category that added functionality to existing classes. We quickly removed the private API calls from our copy of the library and submitted our new application and updates to Apple. </p>

<p>Nonetheless, we found out earlier this week that our new application was rejected  for private API use. The notice from Apple indicated that we had used a private method of

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">UIViewController</div></div>

called

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">previousViewController</div></div>

. Interestingly enough, we did not explicitly use this call anywhere in our code. Looking a bit into the version of the Three20 library we were using revealed that it coincidentally contained a category that added a method to

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">UIViewController</div></div>

called

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">previousViewController</div></div>

.</p>

<p>Once again none of our code or the portions of the Three20 library we used actually exercised this method, but it would appear that the act of compiling and statically linking brings in all the category methods contained in the included headers. I believe that in this case, the <a href="http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocCategories.html">category method overrides</a> the built in method, so I&#8217;m left with the impression that even if we had been exercising the method in question it would have not been actually using the private API.</p>

<p>While this namespace collision problem is often a topic of debate and pain already among Cocoa developers, those of us developing on the iPhone apparently need to take some extra care now because simply choosing the name of a private API method for your own category method name could result in App Store rejection. Even if you are careful to prefix your own category methods, be sure to take extra caution when incorporating foreign code into your project. </p>

<p>Hopefully this and other<a href="http://www.juicybitssoftware.com/2009/11/07/static-analysis-rejection/"> possible false positive problems</a> with the new code analysis portion of App Store submissions will be addressed soon. Personally, I&#8217;d love to see Apple give us access to the analysis tool to run against our own builds before submission. Or if that&#8217;s not possible, perhaps a modification to the review process so this automated analysis happens sooner in the process so we don&#8217;t lose so much ground in the now 14-day wait for the review process to complete. </p>

<p><strong>UPDATE</strong> :
<em><p>After looking at a class-dump of the 3.0 frameworks It looks like</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">previousViewController</div></div>

<p>isn&#8217;t a private API method, but actually a public method on</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">UINavigationController</div></div>

<p>. This leads me to believe that the email from Apple was incorrect in identifying</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">previousViewController</div></div>

<p>as private. Perhaps the analyzer is tripped-up by a category and a subclass defining the same method? If it is just a bug in the analyzer I guess we can&#8217;t really nail down any specific cause of the problem at this time. We made sure there was no trace of any method called</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">previousViewController</div></div>

<p>anywhere in our code, but now I am less certain it will guarantee passing the test next time! </p></em> </p>

<p><em>(Thanks to Andrew Wooster) </em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roguesheep.com/2009/11/19/warning-love-hurts/feed/</wfw:commentRss>
		<slash:comments>33</slash:comments>
		</item>
		<item>
		<title>TapLynx spotted in the wild</title>
		<link>http://blog.roguesheep.com/2009/10/14/taplynx-spotted-in-the-wild/</link>
		<comments>http://blog.roguesheep.com/2009/10/14/taplynx-spotted-in-the-wild/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 06:26:55 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://blog.roguesheep.com/?p=133</guid>
		<description><![CDATA[Our pal Brent Simmons, noted developer of the renowned NetNewsWire for the for the Mac and iPhone, has just released his latest NewsGator project into the wild : TapLynx. 

TapLynx lets you create an iPhone media application without a lick of Objective-C or Cocoa code. Using the SDK you can link against the TapLynx library, [...]]]></description>
			<content:encoded><![CDATA[<p>Our pal Brent Simmons, noted developer of the renowned NetNewsWire for the for the Mac and iPhone, has just released his latest NewsGator project into the wild : <a href="http://inessential.com/2009/10/14/taplynx_1_0">TapLynx</a>. </p>

<p>TapLynx lets you create an iPhone media application without a lick of Objective-C or Cocoa code. Using the SDK you can link against the TapLynx library, configure a plist, edit a few HTML files and in an amazingly short amount of time you&#8217;ll have a custom application presenting content from a variety of sources. The framework is adept at displaying, text, image and video content. The user interface is highly configurable and offers a variety hooks to customize the appearance.</p>

<p></p><p>I took it for a spin this morning and was able to produce this RogueSheep vanity application that featured content from this blog as well as the @postageapp twitter feed in something like 15 or 20 minutes :</p><div style="text-align:center;"><img src="http://blog.roguesheep.com/wp-content/uploads/2009/10/TapLynx-RS-Blog.png" alt="TapLynx - RS Blog.png" border="0" width="212"/></div>

<p>Two nifty features :</p>

<ul>
<li>You can add custom tabs running your own code if you have Cocoa expertise.</li> 

<li>The application configuration can come from a URL, allowing the content and style to update dynamically without submitting a new application instance to the App Store. You can even add new tabs this way!</li>
</ul>

<p>This is a great addition to any iPhone developer&#8217;s toolbox. We are already looking at ways this can help us with several of our clients. Thanks Brent!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roguesheep.com/2009/10/14/taplynx-spotted-in-the-wild/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>UW Course on Mac and iPhone programming</title>
		<link>http://blog.roguesheep.com/2009/07/15/uw-course-on-mac-and-iphone-programming/</link>
		<comments>http://blog.roguesheep.com/2009/07/15/uw-course-on-mac-and-iphone-programming/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 15:39:19 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Macintosh]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://blog.roguesheep.com/?p=102</guid>
		<description><![CDATA[The University of Washington is now offering a certificate course in Macintosh and iPhone programming. 

This program is offered in 3 parts, with the first class that introduces objective-C and Cocoa starting this fall. Our good friend Hal Mueller is teaching the first course. The advisory board for this program is comprised of many of [...]]]></description>
			<content:encoded><![CDATA[<p>The University of Washington is now offering a <a href="http://www.extension.washington.edu/ext/certificates/iph/iph_gen.asp">certificate course in Macintosh and iPhone programming</a>. </p>

<p>This program is offered in 3 parts, with the first class that introduces objective-C and Cocoa starting this fall. Our good friend <a href="http://halmueller.wordpress.com/">Hal Mueller</a> is teaching the first course. The <a href="http://www.extension.washington.edu/ext/certificates/iph/iph_brd.asp">advisory board</a> for this program is comprised of many of the best and well-known Mac and iPhone developers in the region, so you know the content is going to be great.</p>

<p>If you are in the Seattle area and looking to become a master of Cocoa and Objective-C, you don&#8217;t want to miss out on this opportunity. I know that the classes will fill up quick, so apply soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roguesheep.com/2009/07/15/uw-course-on-mac-and-iphone-programming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WWDC 2009!</title>
		<link>http://blog.roguesheep.com/2009/06/05/wwdc-2009/</link>
		<comments>http://blog.roguesheep.com/2009/06/05/wwdc-2009/#comments</comments>
		<pubDate>Sat, 06 Jun 2009 02:27:38 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[RogueSheep]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://blog.roguesheep.com/?p=80</guid>
		<description><![CDATA[RogueSheep is sending a small contingent of the flock next week to the annual Apple Developer conference, WWDC. Our UI whiz and graphic artist, Brad, will be there and of course I will be representing the business and engineering factions. We plan on giving away a few of our new Postage t-shirts as well as [...]]]></description>
			<content:encoded><![CDATA[<p>RogueSheep is sending a small contingent of the flock next week to the annual Apple Developer conference, WWDC. Our UI whiz and graphic artist, Brad, will be there and of course I will be representing the business and engineering factions. We plan on giving away a few of our new Postage t-shirts as well as some reprints of our old company shirt from last year with our updated logo. Follow

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@twenty3</div></div>

on twitter if you&#8217;d like to keep up with where we will be at the conference and to find out how to get a shirt if you are going. </p>

<p>Should be an exciting time for Apple fans with a new MacOS, likely new iPhone hardware and the fresh iPhone OS 3.0. Who knows, maybe even Steve Jobs will descend from the heavens in a divine return to the the helm of the big fruit? I hope to see many of you reading this there.  </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roguesheep.com/2009/06/05/wwdc-2009/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
