<?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>Paul Legato &#187; apple</title>
	<atom:link href="http://www.paullegato.com/blog/tag/apple/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.paullegato.com</link>
	<description></description>
	<lastBuildDate>Tue, 06 Dec 2011 00:52:36 +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>Custom Dialog Boxes Using Cocos2d on iPhone</title>
		<link>http://www.paullegato.com/blog/custom-dialog-boxes-cocos2d-iphone/</link>
		<comments>http://www.paullegato.com/blog/custom-dialog-boxes-cocos2d-iphone/#comments</comments>
		<pubDate>Mon, 13 Dec 2010 10:13:03 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[cocos2d]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[objective c]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=432</guid>
		<description><![CDATA[Custom dialog boxes are a must for any game. iPhone&#8217;s standard dialog boxes are fine for a business or productivity app, but in a game they look out of place. Users play games to escape from their everyday lives. Showing them the same exact graphic design that they associate with work and ordinary routine is [...]]]></description>
			<content:encoded><![CDATA[<p>Custom dialog boxes are a must for any game. iPhone&#8217;s standard dialog boxes are fine for a business or productivity app, but in a game they look out of place. Users play games to escape from their everyday lives. Showing them the same exact graphic design that they associate with work and ordinary routine is a great way to subtly interrupt the immersiveness of their gameplay experience. We don&#8217;t want that, so we need to customize.</p>
<div id="attachment_434"  class="wp-caption center"  style="width: 779px;"><a href="http://www.paullegato.com/wp-content/uploads/2010/12/iPhone-custom-dialog-box.png"  class="galleryAndCaptionItem" title=""><img class="size-full wp-image-434" title="iPhone UIAlertView to custom dialog box example" src="http://www.paullegato.com/wp-content/uploads/2010/12/iPhone-custom-dialog-box.png" alt="iPhone UIAlertView to custom dialog box example. Doesn't the custom one look much better?" width="769" height="268"/></a><span class="wp-caption-text"></span></div>
<p><a target="_blank" href="http://www.cocos2d-iphone.org/" >Cocos2d</a> makes it easy to convert your drab standard UIAlertViews into glorious customized color dialog boxes. Above is an actual UIAlertView / custom dialog box transition from my upcoming iPhone game. Here&#8217;s how I did it. <span id="more-432"></span></p>
<h1>Implementing a Custom Dialog Box in Cocos2d</h1>
<h2>Cocos2d Scene Structure</h2>
<p>Cocos2d uses a <a target="_blank" href="http://en.wikipedia.org/wiki/Scene_graph" >scene graph</a> to hold everything being displayed at any given point in a game. Informally, this data structure is a hierarchy of objects, each of which might display something onscreen, contain other objects to be displayed onscreen, or both. In Cocos2d, these objects are descendants of the <code>CCNode</code> class. </p>
<p>Related objects can be placed into a single container object, which allows them all to be manipulated as a unit when necessary. The root, or lowest-level, container at any given time is an instance of the <code>CCScene</code> class. A <code>CCScene</code> contains <code>CCLayer</code> objects, which themselves contain other objects such as menu labels or sprites to be displayed. Layers, as the name implies, are displayed superimposed upon each other onscreen, which makes a <code>CCLayer</code> perfect for our custom dialog box.</p>
<h2>Custom <code>CCLayer</code></h2>
<p>Here&#8217;s the code for <code>DialogLayer.h</code> and <code>DialogLayer.m</code>. These implement a basic but perfectly servicable custom iPhone dialog box. It can be used as-is or expanded in any number of ways for particular situations. Take a look through the finished product, and then we&#8217;ll go over it below.</p>
<h3><code>DialogLayer.h</code></h3>
<pre class="brush: objc; title: ; notranslate">
//
//  DialogLayer.h
//  concentrate
//
//  Created by Paul Legato on 12/4/10.
//  Copyright 2010 Paul Legato. All rights reserved.
//

#import &lt;Foundation/Foundation.h&gt;
#import &quot;cocos2d.h&quot;

@interface DialogLayer : CCLayer {
  NSInvocation *callback;
}

-(id) initWithHeader:(NSString *)header andLine1:(NSString *)line1 andLine2:(NSString *)line2 andLine3:(NSString *)line3 target:(id)callbackObj selector:(SEL)selector;
-(void) okButtonPressed:(id) sender;

@end
</pre>
<h3><code>DialogLayer.m</code></h3>
<pre class="brush: objc; title: ; notranslate">
//
//  DialogLayer.m
//  concentrate
//
//  Created by Paul Legato on 12/4/10.
//  Copyright 2010 Paul Legato. All rights reserved.
//

#import &quot;DialogLayer.h&quot;
#import &quot;GameSoundManager.h&quot;

#define DIALOG_FONT @&quot;bicho.fnt&quot;

@implementation DialogLayer
-(id) initWithHeader:(NSString *)header andLine1:(NSString *)line1 andLine2:(NSString *)line2 andLine3:(NSString *)line3 target:(id)callbackObj selector:(SEL)selector
 {
   if((self=[super init])) {

     NSMethodSignature *sig = [[callbackObj class] instanceMethodSignatureForSelector:selector];
     callback = [NSInvocation invocationWithMethodSignature:sig];
     [callback setTarget:callbackObj];
     [callback setSelector:selector];
     [callback retain];

     CGSize screenSize = [CCDirector sharedDirector].winSize;

     CCSprite *background = [CCSprite node];
     [background initWithFile:@&quot;Dialog.png&quot;];
     [background setPosition:ccp(screenSize.width / 2, screenSize.height / 2)];
     [self addChild:background z:-1];

     CCLabelBMFont *headerShadow = [CCLabelBMFont labelWithString:header fntFile:DIALOG_FONT];
     headerShadow.color = ccGRAY;
     headerShadow.opacity = 127;
     [headerShadow setPosition:ccp(243, 262)];
     [self addChild:headerShadow];

     CCLabelBMFont *headerLabel = [CCLabelBMFont labelWithString:header fntFile:DIALOG_FONT];
     headerLabel.color = ccBLACK;
     [headerLabel setPosition:ccp(240, 265)];
     [self addChild:headerLabel];

     //////////////////

     CCLabelBMFont *line1Label = [CCLabelBMFont labelWithString:line1 fntFile:DIALOG_FONT];
     line1Label.color = ccBLACK;
     line1Label.scale = 0.84f;
     [line1Label setPosition:ccp(240, 200)];
     [self addChild:line1Label];

     CCLabelBMFont *line2Label = [CCLabelBMFont labelWithString:line2 fntFile:DIALOG_FONT];
     line2Label.color = ccBLACK;
     line2Label.scale = 0.84f;
     [line2Label setPosition:ccp(240, 160)];
     [self addChild:line2Label];

     CCLabelBMFont *line3Label = [CCLabelBMFont labelWithString:line3 fntFile:DIALOG_FONT];
     line3Label.color = ccBLACK;
     line3Label.scale = 0.84f;
     [line3Label setPosition:ccp(240, 120)];
     [self addChild:line3Label];

     CCMenuItemImage *okButton = [CCMenuItemImage itemFromNormalImage:@&quot;OKButton.png&quot; selectedImage:@&quot;OKButtonSelected.png&quot; target:self selector:@selector(okButtonPressed:)];
     [okButton setPosition:ccp(0, 60)];

     CCMenu *menu = [CCMenu menuWithItems: okButton, nil];
     menu.position = ccp(240,0);
     [self addChild:menu];
   }
   return self;
 }

-(void) okButtonPressed:(id) sender
 {
   [[GameSoundManager sharedManager].soundEngine playEffect:@&quot;OK.caf&quot;
                                    pitch:1.0f
                                    pan:0.0f
                                    gain:1.0f];

   [self removeFromParentAndCleanup:YES];
   [callback invoke];
 }

-(void) dealloc
 {
   [callback release];
   [super dealloc];
 }
@end
</pre>
<p><H1>Custom dialog box code analysis</h1>
<h2>Overview</h2>
<p>The dialog box is implemented as a subclass of <code>CCLayer</code>. An <code>initWithHeader</code> method is provided to initialize the layer with a given message and a specified callback method that will be invoked when the dialog&#8217;s &#8220;OK&#8221; button is pressed. It also plays a confirmation sound and switches the &#8220;OK&#8221; button&#8217;s image to a &#8220;pressed button&#8221; when the user taps it.</p>
<p><code>DialogLayer.m</code> requires a few external supports, which must be available as project resources. <code>Dialog.png</code> is the dialog box&#8217;s background image. <code>bicho.fnt</code> is an AngelCode format bitmapped font, used for the labels, and can be substituted with any font you like. <code>OKButton.png</code> and <code>OKButtonSelected.png</code> are the images to be used for the button in unpressed and pressed forms. Finally, <code>OK.caf</code> is the audio file to be played when the user taps the button.</p>
<h2>Analysis</h2>
<h3>Storing the callback</h3>
<pre class="brush: objc; title: ; notranslate">
     NSMethodSignature *sig = [[callbackObj class] instanceMethodSignatureForSelector:selector];
     callback = [NSInvocation invocationWithMethodSignature:sig];
     [callback setTarget:callbackObj];
     [callback setSelector:selector];
     [callback retain];
</pre>
<p>This code is Objective C&#8217;s (massively redundant) way of storing the callback to be activated when the dialog&#8217;s button is pressed. It&#8217;s based on the callback code in Cocos2d itself. (We could also have used <a target="_blank" href="http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html" >Objective C&#8217;s new closure data type, called &#8220;blocks&#8221;</a>, but that syntax grates my Lispy sensibilities even more than the overly verbose Javaish mess here, besides not working out of the box on older versions of iOS.) </p>
<p>The <code>initWithHeader</code> method is given a target object and a method selector. It looks up the class of the target object and then looks up the selector on that class at line 1, resulting in a <code>NSMethodSignature</code> object which encapsulates the class-method combination. Line 2 transforms that class-method signature into an &#8220;invocation,&#8221; which represents the act of actually calling that method on some as yet unspecified object. Line 3 associates the invocation with the particular target object we were given, and line 4 associates the selector (which is utterly odd, since the desired method is encoded in the signature object already.) Finally, we retain the callback so that we can save it for later (to be activated when the user actually presses the &#8220;OK&#8221; button) and it won&#8217;t be deallocated at the end of the present scope.</p>
<h3>Setting up the background and labels</h3>
<p>The remainder of the <code>initWithHeader</code> method, lines 25 to 68 in the main listing above, is pretty straightforward. A <code>CCSprite</code> object is created to store the background image and added to <code>self</code>, that is, to the new custom layer being created. Its position is set to be the center of the screen, and its level on the Z axis is set to -1 so that it will appear below anything else added in the layer.</p>
<p><code>CCLabelBMFont</code>s are then created for the given text and added to the new layer. A shadow effect is created for the header by writing the same thing in grey at a slight offset underneath the main text. All lines except the header are then scaled down to 0.84 of their natural size, so as to enhance the prominence of the header.</p>
<p>A <code>CCMenuItemImage</code> is finally created to be the &#8220;OK&#8221; button. It&#8217;s added to a <code>CCMenu</code>, which handles the logic of button presses for us, and the <code>CCMenu</code> is then added to the new layer. It will take a little experimentation to get the exact placement of the OK button correct (lines 64 and 67) relative to your background image.</p>
<p>Note that the OK button itself takes callback arguments of exactly the same type that our <code>initWithHeader</code> method does (line 63). We might be tempted to forego the construction of our own callback object and just pass the given target and selector on to the OK button, simplifying the design of our <code>DialogLayer</code> a bit, but then we wouldn&#8217;t have the chance to play a sound when the OK buton is pressed. More seriously, we would have no way to destroy the dialog layer and remove it from the screen. So, we give the OK button a target of <code>self</code> and tell it to call the <code>okButtonPressed</code> method when OK is pressed.</p>
<h3>The <code>okButtonPressed</code> callback</h3>
<p>The <code>CCMenuItemImage</code> will invoke this method when the user presses &#8220;OK&#8221;. This means that it&#8217;s time to remove the <code>DialogLayer</code> from the scene (easy enough, line 80). Here, we also play a little click-type sound to make the game seem more interactive; also easy with CocosDenshion, lines 75-78. If you don&#8217;t want to play a sound, you can remove those lines and the <code>GameSoundManager.h</code> include file.</p>
<h3>dealloc</h3>
<p>Nothing fancy here; we just release our retained <code>callback</code> object and then defer to <code>super</code>.</p>
<h1>Using the custom <code>DialogLayer</code></h1>
<p>Adding a custom dialog layer to your game scene is very easy:</p>
<pre class="brush: objc; title: ; notranslate">
   CCLayer *dialogLayer = [[[DialogLayer alloc]
                            initWithHeader:@&quot;Level 1&quot;
                            andLine1:@&quot;Tilt The Phone&quot;
                            andLine2:@&quot;To Balance&quot;
                            andLine3:@&quot;The Ball!&quot;
                            target:self
                            selector:@selector(beginLevelOne)] autorelease];
   [self addChild:dialogLayer z:200];
</pre>
<h1>Future Expansions</h1>
<p><code>DialogLayer</code> is a simple modal dialog box that can only accept one action from the user. It can easily be enhanced in many ways, depending on your needs. The most obvious enhancement is to add multiple buttons to allow the user to make a choice rather than simply dismissing the box. It could be modified to accept an arbitrary amount of text and divide it up automatically into an aesthetically pleasing configuration.</p>
<p>One thing that <code>DialogLayer</code> does <em>not</em> do is pause the game. I decided that that is not necessarily desirable in all cases; many game scenarios need to present information to the user without stopping the action. It&#8217;s easy enough to pause manually when activating the dialog.</p>
<p>Little enhancements like this are critical as &#8216;polish&#8217; for your game.</p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=432&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/custom-dialog-boxes-cocos2d-iphone/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Android or iPhone Development?</title>
		<link>http://www.paullegato.com/blog/android-iphone-development/</link>
		<comments>http://www.paullegato.com/blog/android-iphone-development/#comments</comments>
		<pubDate>Wed, 06 Oct 2010 20:28:40 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=381</guid>
		<description><![CDATA[Which platform should I target first? iPhone, for now, though it's close. Android cannot (yet) provide the same level of developer tools or paying user base, the Android emulator can't handle graphics, and I already own an iPhone. I do expect that Android's competitive position will improve significantly over the next few years, but it's not there yet.]]></description>
			<content:encoded><![CDATA[<p>Android or iPhone? Which platform should I target first? iPhone, for now, though it&#8217;s close. Android cannot (yet) provide the same level of developer tools or paying user base, the Android emulator can&#8217;t handle graphics, and I already own an iPhone. I do expect that Android&#8217;s competitive position will improve significantly over the next few years, but it&#8217;s not there yet.<span id="more-381"></span></p>
<h2>iPhone Pros</h2>
<ul>
<li><strong>iPhones are all (almost) exactly the same.</strong> 4th generation iPhones do support an optional higher screen resolution than previous models, but they&#8217;re 100% binary backwards compatible. This is a trivial difference when put up against the <a href= "https://secure.wikimedia.org/wikipedia/en/wiki/Comparison_of_Android_devices"> dozens of different Android devices</a> available with radically different hardware, and the <a href= "http://developer.android.com/guide/practices/screens_support.html"> hoops that you as a developer have to jump through</a> to make sure your app runs correctly on all of them.</li>
<li><strong>Large, high-end user base that demonstrably spends money on apps.</strong> iPhone users have already shown their willingness to buy large numbers of apps; Android users, not so much. This seems to be slowly changing over time as the Android app store matures, but for now, iPhone is still the cash cow.  </li>
<li><strong>Beautiful and well-designed UI and system architecture.</strong> iPhones have been designed as an integrated and coherent experience. Apple&#8217;s renowned mastery of intuitive human-computer interaction is evident at every step while using the device. There is an overall (and well documented) unifying strategic vision of how different subsystems should fit together seamlessly and present a unified interface to the user. Their development libraries have been designed to support this theme at every level. Android, by contrast, reads much more like KDE or Gnome; it was bolted together out of disparate pieces written by different groups working in isolation with minimal coordination. Perceived technical coolness from the perspective of a software engineer who is already intimately familiar with the system&#8217;s internals took precedent over usability. Android&#8217;s user interface is generally much uglier and much less intuitive.</li>
<li><strong>iPhones support low latency audio.</strong> Android uses ALSA internally, which does support low-latency audio, but the low-latency API is not exposed to developers, and <a href= "https://code.google.com/p/android/issues/detail?id=3434">Google does not seem to be interested in fixing this</a>. Android latency is unacceptably high for realtime sound synthesis unless you hack it and use the ALSA API, which is officially forbidden and in any case could change significantly and without warning between Android operating system updates and between phones. iPhone, on the other hand, has an <a href= "http://developer.apple.com/library/ios/#codinghowtos/AudioAndVideo/index.html#PLAYBACK-MINIMIZE_PLAYBACK_LATENCY"> officially supported low latency audio API</a>, and there are many successful realtime sound synthesizer apps in the app store.</li>
<li><strong>XCode.</strong> XCode is a really well done IDE. I normally don&#8217;t like IDEs. I normally use Emacs for everything. But, in all fairness, I decided to give XCode and Eclipse with the Android plugins a shot. Eclipse is nice, but a little rough around the edges. I ran into a few bizarre IDE error messages while developing my Android test projects that required extensive Googling and hours of experimentation to unravel. XCode, as one would expect from a flagship Apple product, is immaculately polished and completely integrated from top to bottom.</li>
</ul>
<h2>iPhone cons</h2>
<ul>
<li> <strong>Objective C.</strong> While Objective C was really cool and innovative in 1988, today it seems archaic. Nobody uses it except Apple. It&#8217;s laden with tons of cruft. It still feels like it&#8217;s a bolt-on afterthought preprocessor for a C compiler. For example:</p>
<ul>
<li><a href= "http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/ObjectiveC/Articles/ocSelectors.html"><strong>Selectors</strong></a>: you can&#8217;t refer to method names directly; you have to use the special <code>@selector()</code> compiler directive to look up their index number. This probably made great sense when CPUs were very slow and doing a lookup in an ASCII table was a significant performance hit over doing an integer offset jump, but on modern computers, this is just annoying. CPU time is cheaper than engineer time.</li>
<li>
<p><strong>Manual reference-counted memory management is an obsolete and extremely fragile pain in the ass.</strong> Lisp had GC ~40 years ago. The vast set of problems introduced by manual memory management, such as buffer overflows and memory leaks, is just not worth the small gain in efficiency that you get from not periodically running a garbage collector. Again, CPU time is cheaper than engineer time. Android does GC on a phone just fine, so I don&#8217;t buy the argument that a phone can&#8217;t support that kind of overhead. Garbage collection was recently introduced for the Mac OS X desktop system, but is as of yet not available on the iPhone.</p>
<p>(I&#8217;m aware that C and C++ are widely used and both still make you do manual memory management, too. Far from regarding this as a vehicle for a macho display of programming prowess, I find manual memory management to be more of an annoyance, something that the computer should be handling for me automatically, much like how figuring out the exact memory address of a function was automated long ago and is no longer something we as application-level programmers ever need to worry about much.)</p>
</li>
<li><a href= "http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-DontLinkElementID_66"><strong>The use of <code>+</code> and <code>-</code> to mark methods as class or instance methods.</strong></a> Principle of least surprise; why not just use, say, the English word <code>class</code> or <code>static</code> or something to that effect to designate class methods, and leave instance methods unmarked? Perhaps using 1 character symbols rather than entire English words as the token improved compile times on large, complex projects in the &#8217;80s, but the time savings is infinitesimal on a modern computer, so I&#8217;ll vote for obviousness and clarity rather than crypticity.</a></li>
<li><strong>The use of [] (square brackets) for message passing, and the requirement for named (but non-reorderable) arguments.</strong>
<p>Perhaps this was done out of a well-intentioned effort to make the programmer notice that these are messages and not function calls or C++ methods, and to make the code self-documenting. I find the introduction of new syntax rather unwarranted and distracting. I&#8217;d much prefer the familiar <code>object.message(argument1, argument2)</code> over the verbose and unwieldly <code>[object message:argument1 parameterName:argument2]</code>. You can&#8217;t even re-order the named arguments, so including the argument name is just noise in the code. I guess I&#8217;ve been spoiled by Clojure and Lisp, where there&#8217;s almost no syntax.</p>
<p>If they really felt strongly about the need to pedantically differentiate messages from function calls or methods at the syntax level, they should at least have retained the general function/method syntactic template and chosen a different separator character, so as to enable programmers to re-use most of their neural syntax parsing circuitry rather than force us to introduce an entirely new syntactic template that performs only 1 task. For example, a more intuitive syntax that still emphasizes the fact that this is not a function or method call could be something like <code>object#message(argument1, argument2)</code> or <code>object<-message(argument1, argument2)</code>.
 </ul>
</li>
<li><strong>Closed platform.</strong> The source code to the vast Cocoa library is proprietary. You can develop with things Apple tells you you may develop with, and nothing else. They only recently <a target="_blank" href="http://www.macrumors.com/2010/09/09/apple-opens-app-store-to-third-party-development-tools-publishes-review-guidelines/" >relaxed the restriction on using any third party tools</a> at all. <a target="_blank" href="https://encrypted.google.com/search?q=iphone+cpu+java" >The iPhone's CPU is widely reported to have built-in hardware level Java bytecode support</a>, but that's off-limits. </li>
<li><strong>Vendor lock-in.</strong> This is a huge and obvious minus for the iPhone. Your ability to generate revenue is 100% dependent upon Apple's whims, upon remaining in Apple's good graces. Uncountable horror stories circulate online about developers who invested months and many thousands of dollars into a project only to have it rejected by Apple, often after a considerable delay and with little or no explanation.</li>
</ul>
<h2>Android pros</h2>
<ul>
<li><strong>Java (almost).</strong> Android apps are written in Java. (Well, technically not in Java due to licensing issues, but in a language that is 99.9% the same as Java.) If you already know Java, as I do, this is a big plus. You can easily re-use your code elsewhere, on any platform, with minor or no modifications. Objective C code is rather limited in what you can do with it: you can re-use it in your Apple desktop apps. (Yes, there is a free GNU Objective C compiler, but almost all real-world Objective C code is locked into Apple's proprietary Cocoa runtime system.)</li>
<li><strong>A JVM, almost.</strong> Android doesn't run a true JVM, unfortunately, as part of a licensing dispute between Google and Sun, but it's close. Android's <a target="_blank" href="http://en.wikipedia.org/wiki/Dalvik_(software)" >Dalvik</a> is a cleanroom reimplementation of part of Java, designed to avoid triggering what Google regards as onerous licensing fees for the use of a true JVM on a mobile handset. In any case, it's close enough that the door is open to potentially running Clojure and other JVM languages on it someday.</li>
<li><strong>No upfront developer fees. Develop for free.</strong> You can download the SDK and go nuts, upload your code to a real handset to test, send your apps to the app store for sale, whatever. There is no $99 developer tax.  </li>
<li><strong>Larger ultimate user base.</strong> Android phones are now outselling iPhones, and this trend looks set to continue. The price you pay is coding for 200 slightly different handsets.</li>
<li><strong>Open source platform.</strong> Most of the Android system is freely available, precluding vendor lock-in, at least in theory.</li>
</ul>
<h2>Android cons</h2>
<ul>
<li><strong>Android emulator lacks hardware accelerated graphics.</strong> This is a big minus. I made a very simple bouncing-ball demo with <a target="_blank" href="http://www.rokonandroid.com/" >Rokon</a> that got about 6 or 7 fps in the emulator. Full games often take multiple seconds per frame, completely unusable. If you want to write games (or anything else where graphical performance is key), you absolutely need to have a hardware handset from the start. If you don't already own an Android phone anyway, this means you have to invest hundreds of dollars upfront, just to see if the platform is for you.</li>
<li><strong>Lack of interest from Google.</strong> Google has many, many pots cooking at once. While they do devote significant resources to Android's maintenance and expansion, it's nowhere near as important a product for them as the iPhone is for Apple, and you can tell. The iPhone is a core strategic product for Apple, whereas Android is a relatively minor satellite project for Google. Correspondingly, Apple's general support of the iPhone and its developers seems far better.  </li>
<li><strong>Relatively few libraries.</strong> For the moment, there seem to be more third party libraries available for the iPhone, and they seem to be more mature and robust than what's out there for Android. This will change in time, as more and more app developers begin to use Android. </li>
</ul>
<p>It was a close call. I did some exploratory coding on both platforms &mdash; there's no substitute for direct experience. Though I much prefer Java over Objective C as a language, the universe of extant Android libraries is much smaller and less mature. I may have been able to live with that in order to be able to code in Java and avoid Apple's vendor lock-in. In the end, the tipping point was practical: the Android emulator's lack of hardware accelerated graphics left me with an unusable framerate, so I'd have to spend hundreds of dollars on a handset to do even trivial demo development, whereas I already own an iPhone.</p>
<p>I'll be checking back in on Android periodically, as I expect its long-term position will improve substantially in time, but for now, I'm going with the iPhone.</p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=381&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/android-iphone-development/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Launchctl vs Cron: You&#8217;ve Got To Be Kidding Me</title>
		<link>http://www.paullegato.com/blog/launchctl-cron/</link>
		<comments>http://www.paullegato.com/blog/launchctl-cron/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 23:05:30 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=19</guid>
		<description><![CDATA[So I wanted to write a cron job on my Mac. Just run this script every day at midnight. Nothing fancy. In standard Unix, this is one line in a crontab: 0 0 * * * /some/script That&#8217;s it. Put that in your crontab and /some/script will run every day at midnight. Naturally, I typed [...]]]></description>
			<content:encoded><![CDATA[<p>So I wanted to write a cron job on my Mac. Just run this script every day at midnight. Nothing fancy.</p>
<p>In standard Unix, this is <em>one line</em> in a crontab:</p>
<blockquote><p><code>0 0 * * * /some/script</code></p></blockquote>
<p>That&#8217;s it. Put that in your crontab and <code>/some/script</code> will run every day at midnight.</p>
<p>Naturally, I typed <code>man crontab</code> on my Mac to get started. Apple likes to make weird minor modifications to standard Unix commands sometimes. I found:</p>
<blockquote><p>(Darwin note: Although cron(8) and crontab(5) are officially supported under Darwin, their functionality has been absorbed into launchd(8), which provides a more flexible way of automatically executing commands.  See launchctl(1) for more information.)</p></blockquote>
<p>More flexible, huh? I&#8217;m all about more flexible! Sounds good. Another well thought out Apple improvement, sweeping away 30+ years of Unix cruft at a stroke!</p>
<p>Not quite.<span id="more-19"></span> Turns out that you must submit jobs to <code>launchctl</code> as <strong>XML files</strong>. We all know how much I hate XML files, and this is a great example of why. That one line cronjob becomes <a target="_blank" href="http://forums.macosxhints.com/archive/index.php/t-48458.html" >this fragile ~20 line XML monstrosity</a>:</p>
<blockquote><p><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;<br />
&lt;plist version="1.0"&gt;<br />
&lt;dict&gt;<br />
&lt;key&gt;Label&lt;/key&gt;<br />
&lt;string&gt;net.sourceforge.awstats.update-daily&lt;/string&gt;<br />
&lt;key&gt;LowPriorityIO&lt;/key&gt;<br />
&lt;true/&gt;<br />
&lt;key&gt;OnDemand&lt;/key&gt;<br />
&lt;false/&gt;<br />
&lt;key&gt;Program&lt;/key&gt;<br />
&lt;string&gt;/opt/local/www/awstats/cgi-bin/awstats.pl&lt;/string&gt;<br />
&lt;key&gt;ProgramArguments&lt;/key&gt;<br />
&lt;array&gt;<br />
&lt;string&gt;-config=INSERT_YOUR_COMPUTER_NAME_HERE.local&lt;/string&gt;<br />
&lt;string&gt;-update&lt;/string&gt;<br />
&lt;/array&gt;<br />
&lt;key&gt;ServiceDescription&lt;/key&gt;<br />
&lt;string&gt;Updates statistics for awstats.pl every day at 3AM.&lt;/string&gt;<br />
&lt;key&gt;StartCalendarInterval&lt;/key&gt;<br />
&lt;dict&gt;<br />
&lt;key&gt;Hour&lt;/key&gt;<br />
&lt;integer&gt;3&lt;/integer&gt;<br />
&lt;/dict&gt;<br />
&lt;/dict&gt;<br />
&lt;/plist&gt;</code></p></blockquote>
<p>But it defines its own syntax!! I can already hear the XML cheerleaders say. Well, sort of. You can read it, kinda, even if you are unfamiliar with the syntax, but you certainly can&#8217;t write it without spending half an hour or more reading about and then absorbing the syntax documentation first.  For comparison, you can learn the syntax of a crontab entry in around 1 minute. Hell, the <em>documentation</em> of the crontab syntax is shorter than that one simple launchd plist example, nevermind the <a target="_blank" href="http://developer.apple.com/Mac/library/documentation/Darwin/Reference/ManPages/man5/launchd.plist.5.html" >13 page manpage explaining the launchd plist syntax</a>.</p>
<p>More verbosity means more things that can be screwed up, as that discussion thread amply demonstrates. Even extremely simple jobs become ordeals. In this case, the problem stems from <em>trying to do too much in one tool</em>,  forgetting the Unix philosophy: <strong>do one thing, and do it well</strong>. Create reusable, chainable tools, rather than one monolithic beast that tries to do everything. Apple bills <a target="_blank" href="http://www.google.com/search?q=launchd+replaces+site%3Adeveloper.apple.com" >launchd as a replacement for init, rc, init.d, rc.d, SystemStarter, inetd/xinetd, atd, crond, and watchdogd.</a> Maybe others, too.</p>
<p>Developing a language powerful enough to capture the functionality of all of those different tools results in a massively complex, fragile, general-purpose language. Developing a tool that does exactly 1 of those things results in a tiny, simple, clean, resilient language that is easy to use and hard to screw up. Complex cases are then handled by gluing those many small tools together, not by programming a massive monolith.</p>
<p>Fortunately, cron is still supported by Mac OS X as a legacy service, so I&#8217;m using that. If and when they finally remove it from the OS altogether, I&#8217;ll be using the MacPorts version.</p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=19&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/launchctl-cron/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Apple iPad: Axel Payne is Disturbed</title>
		<link>http://www.paullegato.com/blog/apple-ipad-axel-payne-is-disturbed/</link>
		<comments>http://www.paullegato.com/blog/apple-ipad-axel-payne-is-disturbed/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 06:24:59 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[tech industry]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[pretentiousness]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=4</guid>
		<description><![CDATA[The iPad is #1 on Reddit Programming right now: a curious piece by Alex Payne. Payne says he is &#8220;disturbed&#8221; because &#8220;it’s a device that does little to enable creativity&#8221;; thus, the &#8220;tragedy of the iPad is that it truly seems to offer a better model of computing for many people – perhaps the majority [...]]]></description>
			<content:encoded><![CDATA[<p>The iPad is #1 on Reddit Programming right now: a curious <a target="_blank" href="http://al3x.net/2010/01/28/ipad.html" >piece by Alex Payne</a>. Payne says he is &#8220;disturbed&#8221; because &#8220;it’s a device that does little to enable creativity&#8221;; thus, the &#8220;tragedy of the iPad is that it truly seems to offer a better model of computing for many people – perhaps the majority of people.&#8221;</p>
<p>Payne&#8217;s conception of humanity is somewhat more disturbing. He is saying that all people can be, or at least should be, &#8220;creative&#8221; (whatever that means), and those who are not are somehow deficient as human beings. Nonetheless, the iPad so far has not impressed me.<span id="more-4"></span></p>
<p>Payne raises some legitimate points. Admittedly, I&#8217;ve never seen a real one.  If it&#8217;s just a larger iPod Touch, I will never buy it, for many of the reasons Payne describes. I&#8217;ve had an iPhone for a while now, and at this moment, I wouldn&#8217;t buy another one, simply because of the oppressive restrictions on what one is permitted to do with it. I don&#8217;t like having to have Apple&#8217;s imprimatur for software before I&#8217;m allowed to use it. I certainly don&#8217;t like the idea of being forced to pay money for a straight port of a free and open source SSH client that&#8217;s available for a thousand other platforms gratis. I own the hardware, I&#8217;m not renting it. Didn&#8217;t the old AT&amp;T monopoly already go through all this long ago?</p>
<p>I do love the iPhone&#8217;s UI polish, though. It&#8217;s a very tightly integrated device, and everything Just Works. The Android user interface is not yet up to speed &amp;mdash; but it will be, soon. Probably just about the time that my iPhone reaches the end of its useful life, and I&#8217;ll be switching. That is, unless in a moment of sudden enlightenment, Apple removes the DRM from the iPhone and avoids shooting themselves in the foot again by making exactly the same mistake Jobs made 20 years ago with the original Mac. (And by the way, what are we looking forward to in Mac OS XI? Pervasive DRM and an App Store?)</p>
<p>Al3x derides Apple as &#8220;cynical&#8221; for closing the iPad, but it would be just as fair to flip that around and characterize people like Alex Payne as incredibly naive. &#8220;Apple can’t – or won’t – conceive of a future for personal computing that is both elegant and open, usable and free&#8230; Apple has decided that openness is not a quality that’s necessary in a personal computer. That’s disturbing,&#8221; he writes.</p>
<p>Um&#8230; Last I checked, Apple was a for-profit corporation operating in a capitalist economy. This is not secret or hidden information. All such corporations have exactly 1 goal: provide a good return on capital to their shareholders. Anything else that they do is always and exclusively in the service of that goal.</p>
<p>Elegant, open, usable, and free are all nice, sure &amp;mdash; but, for Apple or for any other for-profit corporation, only insofar as doing those things provides a nice return on capital to the shareholders. If they believe that they can get an even better return by dropping them and doing something else instead, then they will.</p>
<p>What&#8217;s really disturbing here is that Payne and more than a few of his friends seem to have actually expected &#8220;nice&#8221; over &#8220;profit&#8221; from a corporation, and are startled and miffed because the corporation chose &#8220;profit&#8221;. &#8220;The iPad leaves me with the feeling that Apple’s interests and values going forward are deeply divergent from my own.&#8221; &#8230; it took the release of the iPad to trigger this epiphany?</p>
<img src="http://www.paullegato.com/?ak_action=api_record_view&id=4&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/apple-ipad-axel-payne-is-disturbed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

