<?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>Mike Laurence&#039;s Internet Playground &#187; Capricious Coding</title>
	<atom:link href="http://blog.mikelaurence.com/posts/category/capricious-coding/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mikelaurence.com</link>
	<description>Mental Meanderings for the Masses</description>
	<lastBuildDate>Fri, 19 Feb 2010 16:31:28 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Dynamic Objective-C for Rubyists</title>
		<link>http://blog.mikelaurence.com/posts/2010/01/dynamic-objective-c-for-rubyists/</link>
		<comments>http://blog.mikelaurence.com/posts/2010/01/dynamic-objective-c-for-rubyists/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 05:59:41 +0000</pubDate>
		<dc:creator>Mike Laurence</dc:creator>
				<category><![CDATA[Capricious Coding]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.mikelaurence.com/?p=111</guid>
		<description><![CDATA[Of the many iPhone developers I’ve encountered, most have transitioned from past lives of hardcore Ruby on Rails development. That shouldn’t be too surprising given the Apple fanboy-ness that many of us exhibit; I’m sure there are Rails developers out there that still develop with Aptana (I used to!), but let’s face it – Rubyists would commit treason to defend the honor of their far-and-above fav, TextMate (especially if version 2.0 were ever released…)

That said, a lot of Rubyists still think Objective-C is the Devil’s language, full of compiler errors and terrifying memory management and other such infernal nonsense. And they’d be right. But what many of them don’t realize is that Objective-C is like your friend’s sexy sister – it’s got all kinds of hot moves, even if it is a little off-putting and the family resemblance strikes fear into your heart.

I’ll do my best to Enumerate (ha!) the dynamic similarities between the languages. If I’ve missed something, let me know!]]></description>
			<content:encoded><![CDATA[<p>
A lot of Rubyists still think Objective-C is the Devil&#8217;s language, full of compiler errors and terrifying memory management and other such infernal nonsense. And they&#8217;d be right. But what many of them don&#8217;t realize is that Objective-C is like your friend&#8217;s sexy sister &#8211; it&#8217;s got all kinds of hot moves, even if it is a little off-putting and the family resemblance a bit unsettling.
</p>
<p>
I&#8217;ll do my best to Enumerate (ha!) the dynamic similarities between the languages. If I&#8217;ve missed something, let me know!
</p>
<ul>
<li><a href="#send">Sending messages</a></li>
<li><a href="#respond_to">respond_to?</a></li>
<li><a href="#dynamic_messages">Dynamic messages</a></li>
<li><a href="#define_method">Defining methods</a></li>
<li><a href="#extend">Extending classes</a></li>
</ul>

<a name="send"></a>
<div class="subheader">
Dear Objective-C object: can I <em>send</em> or <em>__send__</em> you a message?
</div>
<p>
Why yes you can. Simply call performSelector with up to two extra parameters:
</p>

<div class="codecolorer-container objc twitlight" 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;">&#91;</span>obj performSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>myMethod<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#91;</span>obj performSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>myMethod<span style="color: #002200;">&#41;</span> withObject<span style="color: #002200;">:</span>myParameter<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#91;</span>obj performSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>myMethod<span style="color: #002200;">&#41;</span> withObject<span style="color: #002200;">:</span>myParameter withObject<span style="color: #002200;">:</span>anotherParameter<span style="color: #002200;">&#93;</span>;</div></div>

<p>
You can also get a little funky and mess around with threads and delays. These are especially useful if you want to keep your UI updating (such as updating a progress bar while searching for data). Simply use the following:
</p>

<div class="codecolorer-container objc twitlight" 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;">&#91;</span>obj performSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>myMethod<span style="color: #002200;">&#41;</span> withObject<span style="color: #002200;">:</span>myParameter afterDelay<span style="color: #002200;">:</span>2.0<span style="color: #002200;">&#93;</span>;</div></div>

<a name="respond_to"></a>
<div class="subheader">
Shouldn&#8217;t I make sure the object understands the method? You know, Ruby has this <em>respond_to?</em> method&#8230;
</div>
<p>
Wouldn&#8217;t you know it, Objective-C has nearly the same method:
</p>

<div class="codecolorer-container objc twitlight" 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;">SEL</span> dubiousSelector <span style="color: #002200;">=</span> <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>dubiousMethod<span style="color: #002200;">&#41;</span>;<br />
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>obj respondsToSelector<span style="color: #002200;">:</span>dubiousSelector<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><br />
&nbsp; <span style="color: #002200;">&#91;</span>obj performSelector<span style="color: #002200;">:</span>dubiousSelector<span style="color: #002200;">&#93;</span>;</div></div>

<a name="dynamic_messages"></a>
<div class="subheader">
What if I want to construct messages at runtime? I can&#8217;t exactly do that with @selector.
</div>
<p>
Don&#8217;t worry &#8211; Cocoa provides many convenience functions, including <em>NSSelectorFromString</em>, which will allow you to create messages willy-nilly:
</p>

<div class="codecolorer-container objc twitlight" 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;">SEL</span> willyNillySelector <span style="color: #002200;">=</span> NSSelectorFromString<span style="color: #002200;">&#40;</span>aString<span style="color: #002200;">&#41;</span>;<br />
<span style="color: #002200;">&#91;</span>obj performSelector<span style="color: #002200;">:</span>willyNillySelector<span style="color: #002200;">&#93;</span>;</div></div>

<div class="subheader">
But let&#8217;s say I want to get extra freaky with my methods. In Ruby I can use <em>method_missing</em> to catch any message&#8230;
</div>
<p>
Thanks to Ruby and Objective-C&#8217;s shared ancestry of the much-lamented SmallTalk language, you can accomplish dynamic message processing in either. It&#8217;s a bit trickier in Objective-C (specifically Cocoa), but it can be done by defining <em>forwardInvocation</em>.
</p>
<p>
And wouldn&#8217;t you like to know how it works? I would too! But I need to read a little more about it! So stay tuned, &#8216;cuz just like the subject matter, this blog is Dynamic! Ha! Get it!
</p>

<a name="define_method"></a>
<div class="subheader">
Messages are great and all, but what if I want to mess with method implementations themselves? I can simply <em>define_method</em> it up in Ruby&#8230;
</div>
<p>
No problem &#8211; the Objective-C <a href="http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html">runtime</a> has all kinds of fanciness for messing with class and object innards. Although you can&#8217;t yet <a href="http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html">create closures</a> at a whim, you can still switch around implementations.
</p>
<p>
Note: you should always import the following header when utilizing runtime functions:
</p>

<div class="codecolorer-container objc twitlight" 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: #6e371a;">#import &lt;/usr/include/objc/objc-class.h&gt;</span></div></div>

<p>
Some functions you might be interested in for messing around with methods are:
</p>

<div class="codecolorer-container objc twitlight" 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;">BOOL</span> class_addMethod<span style="color: #002200;">&#40;</span><span style="color: #a61390;">Class</span> cls, <span style="color: #a61390;">SEL</span> name, <span style="color: #a61390;">IMP</span> imp, <span style="color: #a61390;">const</span> <span style="color: #a61390;">char</span> <span style="color: #002200;">*</span>types<span style="color: #002200;">&#41;</span><br />
<span style="color: #a61390;">IMP</span> class_replaceMethod<span style="color: #002200;">&#40;</span><span style="color: #a61390;">Class</span> cls, <span style="color: #a61390;">SEL</span> name, <span style="color: #a61390;">IMP</span> imp, <span style="color: #a61390;">const</span> <span style="color: #a61390;">char</span> <span style="color: #002200;">*</span>types<span style="color: #002200;">&#41;</span><br />
<span style="color: #a61390;">IMP</span> class_getMethodImplementation<span style="color: #002200;">&#40;</span><span style="color: #a61390;">Class</span> cls, <span style="color: #a61390;">SEL</span> name<span style="color: #002200;">&#41;</span></div></div>

<p>They each require some or all following information:</p>
<ul>
<li>The class being modified. To modify instances of the class, you&#8217;d pass

<div class="codecolorer-container objc twitlight" 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;">&#91;</span>MyClass class<span style="color: #002200;">&#93;</span></div></div>

in; to modify the class itself, you&#8217;d pass

<div class="codecolorer-container objc twitlight" 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;">&#91;</span>MyClass class<span style="color: #002200;">&#93;</span><span style="color: #002200;">-</span>&gt;isa</div></div>

</li>
<li>The selector (method name) being updated</li>
<li>A Method Implementation (type &#8216;IMP&#8217;), which is just the compiled code that underlies a given method</li>
<li>A string (technically a C character array, so don&#8217;t prepend an @ symbol to it) containing the types of the method signature. The first character represents the return type (&#8221;v&#8221; for void, &#8220;@&#8221; for object references, etc.; those are the most common you&#8217;d use, but there&#8217;s a <a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100">list of type encodings</a> you can refer to for more). The second and third should always be &#8220;@:&#8221;, representing an internal necessity. Any other characters are used to represent the actual argument types.</li>
</ul>
<p>
You probably figured out that the easiest way to define a method implementation (IMP) is to use class_getMethodImplementation. That way, you can do something like the following:
</p>

<div class="codecolorer-container objc twitlight" 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;">IMP</span> myMethodImplementation <span style="color: #002200;">=</span> class_getMethodImplementation<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>MyClass class<span style="color: #002200;">&#93;</span>, <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>methodWithArg<span style="color: #002200;">:</span>andArg<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;<br />
class_replaceMethod<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>OtherClass class<span style="color: #002200;">&#93;</span>, <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>otherMethodWithArg<span style="color: #002200;">:</span>andArg<span style="color: #002200;">&#41;</span>, myMethodImplementation, <span style="color: #bf1d1a;">&quot;v@:@@&quot;</span><span style="color: #002200;">&#41;</span>;</div></div>

<p>
If that seems a little complex, don&#8217;t worry &#8211; it&#8217;s easy enough to boil it down into a convenience method:
</p>

<div class="codecolorer-container objc twitlight" 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: #6e371a;">#import &lt;/usr/include/objc/objc-class.h&gt; &nbsp;</span><br />
<br />
<span style="color: #a61390;">void</span> SwizzleMethod<span style="color: #002200;">&#40;</span><span style="color: #a61390;">Class</span> destClass, <span style="color: #a61390;">SEL</span> destSelector, <span style="color: #a61390;">Class</span> origClass, <span style="color: #a61390;">SEL</span> origSelector, <span style="color: #a61390;">BOOL</span> isInstanceMethod<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; Method dMethod <span style="color: #002200;">=</span> class_getClassMethod<span style="color: #002200;">&#40;</span>isInstanceMethod ? destClass <span style="color: #002200;">:</span> destClass<span style="color: #002200;">-</span>&gt;isa, destSelector<span style="color: #002200;">&#41;</span>;<br />
&nbsp; Method oMethod <span style="color: #002200;">=</span> class_getClassMethod<span style="color: #002200;">&#40;</span>isInstanceMethod ? origClass <span style="color: #002200;">:</span> origClass<span style="color: #002200;">-</span>&gt;isa, origSelector<span style="color: #002200;">&#41;</span>;<br />
&nbsp; <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>class_addMethod<span style="color: #002200;">&#40;</span>isInstanceMethod ? destClass <span style="color: #002200;">:</span> destClass<span style="color: #002200;">-</span>&gt;isa, destSelector, method_getImplementation<span style="color: #002200;">&#40;</span>oMethod<span style="color: #002200;">&#41;</span>, method_getTypeEncoding<span style="color: #002200;">&#40;</span>oMethod<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span><br />
&nbsp; &nbsp; method_exchangeImplementations<span style="color: #002200;">&#40;</span>dMethod, oMethod<span style="color: #002200;">&#41;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #11740a; font-style: italic;">// Example instance method usage:</span><br />
SwizzleMethod<span style="color: #002200;">&#40;</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> class<span style="color: #002200;">&#93;</span>, <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>length<span style="color: #002200;">&#41;</span>, <span style="color: #002200;">&#91;</span>MyClass class<span style="color: #002200;">&#93;</span>, <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>customLength<span style="color: #002200;">&#41;</span>, <span style="color: #a61390;">YES</span><span style="color: #002200;">&#41;</span>;<br />
<br />
<span style="color: #11740a; font-style: italic;">// Example class method usage:</span><br />
SwizzleMethod<span style="color: #002200;">&#40;</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> class<span style="color: #002200;">&#93;</span>, <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">string</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">&#91;</span>MyClass class<span style="color: #002200;">&#93;</span>, <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>customCreator<span style="color: #002200;">&#41;</span>, <span style="color: #a61390;">NO</span><span style="color: #002200;">&#41;</span>;</div></div>

<p>
You can put the SwizzleMethod function into a file and include it globally in your prefix header (usually named something like MyProject_Prefix.pch).
</p>


<a name="extend"></a>
<div class="subheader">
How about extending existing classes? I&#8217;d love to add some ActiveSupport-style convenience methods&#8230;
</div>
<p>
First of all, be sure to check out the <a href="http://github.com/yfactorial/objectivesupport">Objective Support</a> project, which accomplishes a lot of the goodness you&#8217;re used to from ActiveSupport.
</p>
<p>
Objective Support does its magic largely through the use of <em>categories</em>, which are a nice mixin-style feature of Objective-C. Essentially, categories allow you to &#8220;re-open&#8221; classes just like Ruby; you can create multiple categories for any given class and insert methods as you see fit. You can&#8217;t add instance variables, but you can override existing methods.
</p>
<p>
Thankfully, the implementation of categories is fairly simple:
</p>

<div class="codecolorer-container objc twitlight" 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: #11740a; font-style: italic;">/* Define the category's interface. In this case, we're<br />
&nbsp; &nbsp;re-opening NSString and calling our category &quot;Utils&quot; */</span><br />
<span style="color: #a61390;">@interface</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;">&#40;</span>Utils<span style="color: #002200;">&#41;</span><br />
<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> split;<br />
<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> split<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>delimiter;<br />
<span style="color: #a61390;">@end</span><br />
<br />
<span style="color: #11740a; font-style: italic;">// Implement the category's interface</span><br />
<span style="color: #a61390;">@implementation</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;">&#40;</span>Utils<span style="color: #002200;">&#41;</span><br />
<br />
<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> split <span style="color: #002200;">&#123;</span><br />
&nbsp; <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self split<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;,&quot;</span><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><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> split<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>delimiter <span style="color: #002200;">&#123;</span><br />
&nbsp; <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self componentsSeparatedByString<span style="color: #002200;">:</span>delimiter<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
<br />
<span style="color: #a61390;">@end</span></div></div>

<p>
Note: you may want to include your category header in your prefix header (or at least the classes in which its methods get called), as otherwise you&#8217;ll see a bunch of &#8220;object may not respond to xxxx&#8221; warnings.
</p>

<div class="subheader">
Neat-o! They should just call it &#8220;Dynamic-C&#8221;!
</div>
<p>
This is by no means an exhaustive list of Objective-C&#8217;s dynamism, but it covers a lot of the goodies. If there&#8217;s something I left off that you earnestly believe should be here, or you see a (gasp!) code error, let me know!
</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mikelaurence.com/posts/2010/01/dynamic-objective-c-for-rubyists/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Individually Rounded Corners for your iPhone iPleasure</title>
		<link>http://blog.mikelaurence.com/posts/2010/01/individually-rounded-corners-for-your-iphone-ipleasure/</link>
		<comments>http://blog.mikelaurence.com/posts/2010/01/individually-rounded-corners-for-your-iphone-ipleasure/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 22:27:54 +0000</pubDate>
		<dc:creator>Mike Laurence</dc:creator>
				<category><![CDATA[Capricious Coding]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://blog.mikelaurence.com/?p=100</guid>
		<description><![CDATA[
Everyone likes rounded corners (except Internet Explorer, but who cares?). By now, we&#8217;re used to simple declarations to get our hot sexy web 2.0 roundedness in Webkit and Firefox:


border-radius: 10px;


Or if you want to get really freaky, you can define radii individually for each corner (unfortunately this syntax varies by rendering engine):


-webkit-border-top-right-radius: 10px;
-webkit-border-bottom-left-radius: 20px;


Now, if [...]]]></description>
			<content:encoded><![CDATA[<p>
Everyone likes rounded corners (except Internet Explorer, but who cares?). By now, we&#8217;re used to simple declarations to get our hot sexy web 2.0 roundedness in Webkit and Firefox:
</p>

<div class="codecolorer-container objc twitlight" 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">border<span style="color: #002200;">-</span>radius<span style="color: #002200;">:</span> 10px;</div></div>

<p>
Or if you want to get really freaky, you can define radii individually for each corner (unfortunately this syntax varies by rendering engine):
</p>

<div class="codecolorer-container objc twitlight" 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>webkit<span style="color: #002200;">-</span>border<span style="color: #002200;">-</span>top<span style="color: #002200;">-</span>right<span style="color: #002200;">-</span>radius<span style="color: #002200;">:</span> 10px;<br />
<span style="color: #002200;">-</span>webkit<span style="color: #002200;">-</span>border<span style="color: #002200;">-</span>bottom<span style="color: #002200;">-</span>left<span style="color: #002200;">-</span>radius<span style="color: #002200;">:</span> 20px;</div></div>

<p>
Now, if there&#8217;s anything I&#8217;ve learned about developing for the iPhone, it&#8217;s that it takes 10 times as much work as web development. Rounded corners were no exception, until iPhone OS 3.0 released this little gem:
</p>

<div class="codecolorer-container objc twitlight" 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: #6e371a;">#import &lt;QuartzCore/QuartzCore.h&gt;</span><br />
CALayer<span style="color: #002200;">*</span> layer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>myUIView layer<span style="color: #002200;">&#93;</span>;<br />
layer.cornerRadius <span style="color: #002200;">=</span> <span style="color: #2400d9;">10.0</span>;</div></div>

<p>
Suddenly rounding corners on the iPhone was as easy as slicing bread. Yet there is no way to round individual corners like in a web browser, and much more importantly, <em>using cornerRadius will kill your performance</em> &#8211; especially on older devices. Sure, you can get by if you just have one or two rounded views and no scrolling, but we should haven&#8217;t to limit the glory of our rounded revolution, now should we?
</p>
<p>
Because I needed excellent performance with many simultaneous views as well as individually rounded corners, I opted to see what else I could come up with. Luckily, there were <a href="http://blog.sallarp.com/iphone-uiimage-round-corners/">several</a> <a href="http://softwaremaven.innerbrane.com/2009/05/rounding-corners-on-uiview.html">examples</a> on the interwebs with good techniques, though none gave me a simple way to round corners individually. So, after a little sweat, I came up with the following code for you, my dear readers, to use and nuture and love:
</p>
<b>CGFunctions.h</b>

<div class="codecolorer-container objc twitlight" 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: #11740a; font-style: italic;">//</span><br />
<span style="color: #11740a; font-style: italic;">// &nbsp;CGFunctions.h</span><br />
<span style="color: #11740a; font-style: italic;">// &nbsp;OccoTouch</span><br />
<span style="color: #11740a; font-style: italic;">//</span><br />
<span style="color: #11740a; font-style: italic;">// &nbsp;Created by Mike Laurence on 1/11/10.</span><br />
<span style="color: #11740a; font-style: italic;">// &nbsp;Copyright 2010 Punkbot LLC. All rights reserved.</span><br />
<span style="color: #11740a; font-style: italic;">//</span><br />
<br />
<span style="color: #6e371a;">#pragma mark -</span><br />
<span style="color: #6e371a;">#pragma mark Rounded Corners</span><br />
<span style="color: #a61390;">void</span> CGContextAddRoundedRect<span style="color: #002200;">&#40;</span>CGContextRef context, CGRect rect, <span style="color: #a61390;">int</span> inset, <span style="color: #a61390;">int</span> ul, <span style="color: #a61390;">int</span> ur, <span style="color: #a61390;">int</span> lr, <span style="color: #a61390;">int</span> ll<span style="color: #002200;">&#41;</span>;</div></div>

<b>CGFunctions.m</b>

<div class="codecolorer-container objc twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:300px;"><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #11740a; font-style: italic;">//</span><br />
<span style="color: #11740a; font-style: italic;">// &nbsp;CGFunctions.m</span><br />
<span style="color: #11740a; font-style: italic;">// &nbsp;RoundedCorners</span><br />
<span style="color: #11740a; font-style: italic;">//</span><br />
<span style="color: #11740a; font-style: italic;">// &nbsp;Created by Mike Laurence on 1/11/10.</span><br />
<span style="color: #11740a; font-style: italic;">// &nbsp;Copyright 2010 Punkbot LLC. All rights reserved.</span><br />
<span style="color: #11740a; font-style: italic;">//</span><br />
<br />
<span style="color: #6e371a;">#import &quot;CGFunctions.h&quot;</span><br />
<br />
<span style="color: #6e371a;">#pragma mark -</span><br />
<span style="color: #6e371a;">#pragma mark Rounded Corners</span><br />
<br />
<span style="color: #a61390;">void</span> CGContextAddRoundedRect<span style="color: #002200;">&#40;</span>CGContextRef context, CGRect rect, <span style="color: #a61390;">int</span> inset, <span style="color: #a61390;">int</span> ul, <span style="color: #a61390;">int</span> ur, <span style="color: #a61390;">int</span> lr, <span style="color: #a61390;">int</span> ll<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
<br />
&nbsp; &nbsp; CGContextSaveGState<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">int</span> xLeft <span style="color: #002200;">=</span> rect.origin.x <span style="color: #002200;">+</span> inset;<br />
&nbsp; &nbsp; <span style="color: #a61390;">int</span> xRight <span style="color: #002200;">=</span> rect.origin.x <span style="color: #002200;">+</span> rect.size.width <span style="color: #002200;">-</span> inset;<br />
&nbsp; &nbsp; <span style="color: #a61390;">int</span> yTop <span style="color: #002200;">=</span> rect.origin.y <span style="color: #002200;">+</span> inset;<br />
&nbsp; &nbsp; <span style="color: #a61390;">int</span> yBottom <span style="color: #002200;">=</span> rect.origin.y <span style="color: #002200;">+</span> rect.size.height <span style="color: #002200;">-</span> inset;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>ul &gt; 0<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextMoveToPoint<span style="color: #002200;">&#40;</span>context, xLeft, yTop <span style="color: #002200;">+</span> ul<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextAddArcToPoint<span style="color: #002200;">&#40;</span>context, xLeft, yTop, xLeft <span style="color: #002200;">+</span> ul, yTop, ul<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextMoveToPoint<span style="color: #002200;">&#40;</span>context, xLeft, yTop<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>ur &gt; 0<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextAddLineToPoint<span style="color: #002200;">&#40;</span>context, xRight <span style="color: #002200;">-</span> ur, yTop<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextAddArcToPoint<span style="color: #002200;">&#40;</span>context, xRight, yTop, xRight, yTop <span style="color: #002200;">+</span> ur, ur<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextAddLineToPoint<span style="color: #002200;">&#40;</span>context, xRight, yTop<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>lr &gt; 0<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextAddLineToPoint<span style="color: #002200;">&#40;</span>context, xRight, yBottom <span style="color: #002200;">-</span> lr<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextAddArcToPoint<span style="color: #002200;">&#40;</span>context, xRight, yBottom, xRight <span style="color: #002200;">-</span> lr, yBottom, lr<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextAddLineToPoint<span style="color: #002200;">&#40;</span>context, xRight, yBottom<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>ll &gt; 0<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextAddLineToPoint<span style="color: #002200;">&#40;</span>context, xLeft <span style="color: #002200;">+</span> ll, yBottom<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextAddArcToPoint<span style="color: #002200;">&#40;</span>context, xLeft, yBottom, xLeft, yBottom <span style="color: #002200;">-</span> ll, ll<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CGContextAddLineToPoint<span style="color: #002200;">&#40;</span>context, xLeft, yBottom<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; CGContextClosePath<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>; <br />
&nbsp; &nbsp; CGContextRestoreGState<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>; <br />
<span style="color: #002200;">&#125;</span></div></div>

<p>
(<a href="http://mikelaurence.com/iPhone-RoundedCorners.zip">Full sample project</a>)
</p>
<p>
This draws a path on your graphics context, which can then be used to draw outlines or fill with colors/patterns/etc. 
</p>
<p>
Notes:
</p>
<ul>
<li>
<p>
Because CGContextAddRoundedRect is defined as a function and not a method of some class, you&#8217;ll need to do a little configuration to get your compiler to accept it. Mainly, find your project&#8217;s precompiled header file (it should be called something like ProjectName_Prefix.pch) and insert the following line:
</p>

<div class="codecolorer-container objc twitlight" 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: #6e371a;">#import &quot;CGFunctions.h&quot;</span></div></div>

<p>
That will allow you to use the function anywhere in your code.
</p>
</li>
<li>
<p>
Watch out for the stroke going outside the view rectangle &#8211; you may get weird, uneven-looking drawing. I&#8217;ve provided an &#8220;inset&#8221; parameter in the CGContextAddRoundedRect function so that you can avoid just that. A good rule of thumb is to provide the same value to the inset as you do to your stroke width (you may know it as line width, set via the CGContextSetLineWidth function).
</p>
</li>
</ul>
<p>
Here&#8217;s a simple example of using CGContextAddRoundedRect in practice:
</p>

<div class="codecolorer-container objc twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:300px;"><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> drawRect<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGRect<span style="color: #002200;">&#41;</span>rect <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Get graphics context for this view</span><br />
&nbsp; &nbsp; CGContextRef context <span style="color: #002200;">=</span> UIGraphicsGetCurrentContext<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Set our fill color</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>fillColor set<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Add the path and fill. Note that our inset parameter (3rd param) is equal to our stroke width.</span><br />
&nbsp; &nbsp; CGContextAddRoundedRect<span style="color: #002200;">&#40;</span>context, rect, strokeWidth, upperLeftRadius, upperRightRadius, lowerRightRadius, lowerLeftRadius<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; CGContextFillPath<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Set our stroke color</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>strokeColor set<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Set our stroke width</span><br />
&nbsp; &nbsp; CGContextSetLineWidth<span style="color: #002200;">&#40;</span>context, strokeWidth<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Add the path again and fill</span><br />
&nbsp; &nbsp; CGContextAddRoundedRect<span style="color: #002200;">&#40;</span>context, rect, strokeWidth, upperLeftRadius, upperRightRadius, lowerRightRadius, lowerLeftRadius<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; CGContextStrokePath<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>;<br />
<span style="color: #002200;">&#125;</span></div></div>

<p>
In addition to painting, you can also use paths to mask images and do all kinds of other fun stuff with Quartz (check out <a href="http://blog.sallarp.com/iphone-uiimage-round-corners/">this article</a> for some sample image masking code).
</p>
<p>
That ought to get you started. Now, go forth and spread the rounded corner love!
</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mikelaurence.com/posts/2010/01/individually-rounded-corners-for-your-iphone-ipleasure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick, Convert Your RubyCocoa To MacRuby!</title>
		<link>http://blog.mikelaurence.com/posts/2009/05/quick-convert-your-rubycocoa-to-macruby/</link>
		<comments>http://blog.mikelaurence.com/posts/2009/05/quick-convert-your-rubycocoa-to-macruby/#comments</comments>
		<pubDate>Sat, 23 May 2009 17:33:30 +0000</pubDate>
		<dc:creator>Mike Laurence</dc:creator>
				<category><![CDATA[Capricious Coding]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[macruby]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubycocoa]]></category>

		<guid isPermaLink="false">http://mikelaurence.com/?p=43</guid>
		<description><![CDATA[You won&#8217;t regret it. Really. MacRuby is like filet mignon, while RubyCocoa is just a sad, undercooked rumproast. Did I just paraphrase a joke from American Pie 2? You better believe it, buster.


Anyway, if you have a RubyCocoa project that needs a little bit of shininess, it may be surprisingly easy (and satisfying) to quickly [...]]]></description>
			<content:encoded><![CDATA[You won&#8217;t regret it. Really. MacRuby is like filet mignon, while RubyCocoa is just a sad, undercooked rumproast. Did I just paraphrase a joke from American Pie 2? You better believe it, buster.
<br />
<br />
Anyway, if you have a RubyCocoa project that needs a little bit of shininess, it may be surprisingly easy (and satisfying) to quickly port it over to MacRuby. I just spent about 4 hours converting a fairly sophisticated app (aside from its MIDI interface, which is a bit more tricky, but you probably won&#8217;t be dealing with that).
<br />
<br />
My first stop was <a href="http://www.cuppadev.co.uk/hacks/converting-rubycocoa-projects-to-macruby/">this post</a>, a very nice summary of the basic steps that need to be taken. However, I encountered quite a few additional snags, and I thought I&#8217;d post them just in case you, random internet denizen, want to skip them all together. Most of them are covered in the MacRuby docs, of course, but they&#8217;re here in a nice digestible table format so you can more easily knock out your conversion. Because as fun as prettying up your code is, you&#8217;d still rather be adding functionality, right?
<br />
<br />
<span id="more-43"></span>
<style type="text/css">
  .widget { display: none }
  .code_header { padding-top: 25px; text-align: center; }
</style>
<table>
  <tr>
    <th style="text-align:center;color:black">RubyCocoa</th>
    <th style="text-align:center;color:black">MacRuby</th>
  </tr>
  <tr>
    <td colspan="2" class="code_header">
      The basics
    </td>
  </tr>
  <tr>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ib_outlet <span style="color:#ff3333; font-weight:bold;">:property</span></div></div>

</td>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">attr_writer <span style="color:#ff3333; font-weight:bold;">:property</span></div></div>

</td>
  </tr>
  <tr>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ib_action <span style="color:#ff3333; font-weight:bold;">:method</span><br />
<span style="color:#9966CC; font-weight:bold;">def</span> method<span style="color:#006600; font-weight:bold;">&#40;</span>sender<span style="color:#006600; font-weight:bold;">&#41;</span>...</div></div>

</td>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># Just ditch the ib_action call!</span><br />
<span style="color:#9966CC; font-weight:bold;">def</span> method<span style="color:#006600; font-weight:bold;">&#40;</span>sender<span style="color:#006600; font-weight:bold;">&#41;</span>...</div></div>

</td>
  </tr>
  <tr>
    <td colspan="2" class="code_header">
      Key-value coding (KVC)
    </td>
  </tr>
  <tr>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">kvc_accessor <span style="color:#ff3333; font-weight:bold;">:property</span></div></div>

</td>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">attr_accessor <span style="color:#ff3333; font-weight:bold;">:property</span></div></div>

</td>
  </tr>
  <tr>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># Default setter automatically notifies</span><br />
property = <span style="color:#996600;">'new hotness'</span></div></div>

</td>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># Have to use notifying method (for now...)</span><br />
setValue <span style="color:#996600;">'new hotness'</span>, forKey:<span style="color:#996600;">'property'</span></div></div>

</td>
  </tr>
  <tr>
    <td colspan="2" class="code_header">
      Setting an action selector
    </td>
  </tr>
  <tr>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#0066ff; font-weight:bold;">@table</span>.<span style="color:#9900CC;">setDoubleAction</span> <span style="color:#ff3333; font-weight:bold;">:doubleClick</span></div></div>

</td>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#0066ff; font-weight:bold;">@table</span>.<span style="color:#9900CC;">setDoubleAction</span> <span style="color:#996600;">'doubleClick:'</span></div></div>

</td>
  </tr>
  <tr>
    <td colspan="2" class="code_header">
      Dealing with Cocoa&#8217;s funky named parameters
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># Parameter names are included in method name,</span><br />
<span style="color:#008000; font-style:italic;"># separated by underscores; values follow</span><br />
<span style="color:#008000; font-style:italic;"># in sequential order</span><br />
year.<span style="color:#9900CC;">setValue_forKey</span> <span style="color:#006666;">525600</span>, <span style="color:#996600;">'minutes'</span></div></div>

</td>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># Only the first parameter name (&quot;value&quot;) is</span><br />
<span style="color:#008000; font-style:italic;"># included in &nbsp;the method signature; the rest can be </span><br />
<span style="color:#008000; font-style:italic;"># defined with Ruby 1.9's named parameter support:</span><br />
year.<span style="color:#9900CC;">setValue</span> <span style="color:#006666;">525600</span>, forKey:<span style="color:#996600;">'minutes'</span><br />
<br />
<span style="color:#008000; font-style:italic;"># Or, alternatively, a hash:</span><br />
year.<span style="color:#9900CC;">setValue</span> 525600, <span style="color:#ff3333; font-weight:bold;">:forKey</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'minutes'</span></div></div>

</td>
  </tr>
  <tr>
    <td colspan="2" class="code_header">
      Overriding Cocoa&#8217;s funky named parameters
    </td>
  </tr>
  <tr>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">def</span> drawInteriorWithFrame_inView<span style="color:#006600; font-weight:bold;">&#40;</span>frame, controlView<span style="color:#006600; font-weight:bold;">&#41;</span></div></div>

</td>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">def</span> drawInteriorWithFrame<span style="color:#006600; font-weight:bold;">&#40;</span>frame, inView:controlView<span style="color:#006600; font-weight:bold;">&#41;</span></div></div>

</td>
  </tr>
  <tr>
    <td colspan="2" class="code_header">
      Calling the current method in the superclass
    </td>
  </tr>
  <tr>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">super_drawInteriorWithFrame_inView<span style="color:#006600; font-weight:bold;">&#40;</span>frame, controlView<span style="color:#006600; font-weight:bold;">&#41;</span></div></div>

</td>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">super</span> <span style="color:#008000; font-style:italic;"># Now that's what I'm talking about!</span></div></div>

</td>
  </tr>
  <tr>
    <td colspan="2" class="code_header">
      Instantiating collections
    </td>
  </tr>
  <tr>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">array</span> = NSMutableArray.<span style="color:#9900CC;">alloc</span>.<span style="color:#9900CC;">init</span><br />
hash = NSMutableDictionary.<span style="color:#9900CC;">alloc</span>.<span style="color:#9900CC;">init</span></div></div>

</td>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">array</span> = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#008000; font-style:italic;"># It's a real NSMutableArray!</span><br />
hash = <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#008000; font-style:italic;"># It's a real NSMutableDictionary!</span></div></div>

</td>
  </tr>
  <tr>
    <td colspan="2" class="code_header">
      Instantiating objects
    </td>
  </tr>
  <tr>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">table = NSArrayController.<span style="color:#9900CC;">alloc</span>.<span style="color:#9900CC;">init</span></div></div>

</td>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">table = NSArrayController.<span style="color:#9900CC;">new</span></div></div>

</td>
  </tr>
  <tr>
    <td colspan="2" class="code_header">
      Defining class initializers
    </td>
  </tr>
  <tr>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">def</span> init<br />
&nbsp; super_init <span style="color:#008000; font-style:italic;"># If a Cocoa subclass</span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># Do stuff</span><br />
&nbsp; <span style="color:#0000FF; font-weight:bold;">self</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>

</td>
    <td>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">def</span> initialize<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">super</span> <span style="color:#008000; font-style:italic;"># If a Cocoa subclass</span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># Do stuff. Note: you can still override #init,</span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># but then you must return self.</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>

</td>
  </tr>
</table>
Also, if you&#8217;re in the habit of grouping your code into directories, the default loadup require scheme might not work for you, as it only grabs the files in the root directory. Just change that Dir.entries to a Dir.glob and you&#8217;ll be all set:

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># In rb_main.rb</span><br />
ROOT = NSBundle.<span style="color:#9900CC;">mainBundle</span>.<span style="color:#9900CC;">resourcePath</span>.<span style="color:#9900CC;">fileSystemRepresentation</span><br />
<span style="color:#CC00FF; font-weight:bold;">Dir</span>.<span style="color:#9900CC;">glob</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{ROOT}/**/*.rb&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>file<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> file != <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">basename</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">require</span><span style="color:#006600; font-weight:bold;">&#40;</span>file<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<br />
And that&#8217;s just for starters! If I remember or encounter anything else, I&#8217;ll be sure to append this post. And don&#8217;t you dare think this is conclusive &#8211; the wonderful folks working on <a href="http://www.macruby.org/hotcocoa.html">HotCocoa</a> have been streamlining things for even greater efficiency, so be sure to check that out.
]]></content:encoded>
			<wfw:commentRss>http://blog.mikelaurence.com/posts/2009/05/quick-convert-your-rubycocoa-to-macruby/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Apparently Apple&#8217;s App Store Databases Are So Complex That They Take 5+ Weeks To Update My Goddamn Name</title>
		<link>http://blog.mikelaurence.com/posts/2009/05/apparently-apples-app-store-databases-are-so-complex-that-they-take-5-weeks-to-update-my-goddamn-name/</link>
		<comments>http://blog.mikelaurence.com/posts/2009/05/apparently-apples-app-store-databases-are-so-complex-that-they-take-5-weeks-to-update-my-goddamn-name/#comments</comments>
		<pubDate>Wed, 13 May 2009 22:15:58 +0000</pubDate>
		<dc:creator>Mike Laurence</dc:creator>
				<category><![CDATA[Capricious Coding]]></category>
		<category><![CDATA[app store]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://mikelaurence.com/?p=39</guid>
		<description><![CDATA[You can be up and running on the App Store in 24 hours if you want to parade your apps around under your own name.

However, apparently the additional overhead of having a company name adds so much stress to Apple&#8217;s systems that you&#8217;re placed in a queue and told to be patient while your &#8220;updates&#8221; [...]]]></description>
			<content:encoded><![CDATA[You can be up and running on the App Store in 24 hours if you want to parade your apps around under your own name.
<br /><br />
However, apparently the additional overhead of having a company name adds so much stress to Apple&#8217;s systems that you&#8217;re placed in a queue and told to be patient while your &#8220;updates&#8221; chug along for FIVE weeks. And COUNTING.
<br /><br />
So, developers be warned &#8211; think of your company name NOW, file for an LLC, and submit for an account (or conversion of an account, like I did) before you even begin programming. Because sitting around for weeks with a ready-to-go application sucks.
<br /><br />
Also, definitely <a href="http://developer.apple.com/contact/phone.html">telephone the developer connection</a> if you need to convert from an individual to company account. Don&#8217;t just send them an e-mail. I did that at first, and I never in three weeks even received a response. I had to actually call in to get things rolling (and then I had to *fax* my business documents in. What is this Apple, 1984? I thought you were running in slow motion and throwing objects through large oppressive screens?)]]></content:encoded>
			<wfw:commentRss>http://blog.mikelaurence.com/posts/2009/05/apparently-apples-app-store-databases-are-so-complex-that-they-take-5-weeks-to-update-my-goddamn-name/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Your mobile device has encountered an unexpected error (0xE8000001)</title>
		<link>http://blog.mikelaurence.com/posts/2009/05/your-mobile-device-has-encountered-an-unexpected-error-0xe8000001/</link>
		<comments>http://blog.mikelaurence.com/posts/2009/05/your-mobile-device-has-encountered-an-unexpected-error-0xe8000001/#comments</comments>
		<pubDate>Sun, 10 May 2009 00:14:50 +0000</pubDate>
		<dc:creator>Mike Laurence</dc:creator>
				<category><![CDATA[Capricious Coding]]></category>
		<category><![CDATA[app store]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://mikelaurence.com/?p=30</guid>
		<description><![CDATA[If you&#8217;re building &#038; deploying apps to your iPhone, you may encounter this dreaded and shamefully unhelpful error message at some time. It&#8217;s happened twice to me; the first time, after scouring the Internets for answers, it looked like I only had a couple of choices: either jailbreak my iPhone and do some SSH trickery [...]]]></description>
			<content:encoded><![CDATA[If you&#8217;re building &#038; deploying apps to your iPhone, you may encounter this dreaded and shamefully unhelpful error message at some time. It&#8217;s happened twice to me; the first time, after scouring the Internets for answers, it looked like I only had a couple of choices: either <a href="http://nullreference.wordpress.com/2008/12/19/your-mobile-device-has-encountered-an-unexpected-error-0xe8000001/">jailbreak my iPhone and do some SSH trickery</a> or restore to a previous version. I went for restoring, and it was even more irritating than I thought it would be.
<br /><br />
But you don&#8217;t have to restore your phone, and you don&#8217;t need to jailbreak, either; just change the application&#8217;s package identifier:
<br />

<div class="codecolorer-container text twitlight" 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">com.initech.jumptoconclusions</div></div>

=>
<br />

<div class="codecolorer-container text twitlight" 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">com.initech.jumptoconclusions2</div></div>

<br /><br />
The hidden problem (as explained by the post linked to above) is that there are broken bits of your app hanging around in an inaccessible folder on the iPhone. However, if you change the package name, it will use a different folder for deployment, so you will no longer be dealing with the broken parts.
<br /><br />
Of course, if you&#8217;re really sold on that initial app identifier, then you&#8217;ll have to restore or jailbreak eventually. But maybe by the time your app is ready to send off to the Committee of Endless Deliberation, you&#8217;ll be on the next OS, and it will have some sort of automatic cleanup to deal with this issue. I mean, it had better.]]></content:encoded>
			<wfw:commentRss>http://blog.mikelaurence.com/posts/2009/05/your-mobile-device-has-encountered-an-unexpected-error-0xe8000001/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Flex Benchmarks Are Fun For the Whole Family!</title>
		<link>http://blog.mikelaurence.com/posts/2008/06/flex-benchmarks-are-fun-for-the-whole-family/</link>
		<comments>http://blog.mikelaurence.com/posts/2008/06/flex-benchmarks-are-fun-for-the-whole-family/#comments</comments>
		<pubDate>Mon, 16 Jun 2008 01:44:14 +0000</pubDate>
		<dc:creator>Mike Laurence</dc:creator>
				<category><![CDATA[Capricious Coding]]></category>
		<category><![CDATA[flex code benchmarking]]></category>

		<guid isPermaLink="false">http://mikelaurence.com/?p=7</guid>
		<description><![CDATA[I&#8217;ve spent the last few months digging deep into ActionScript, the programming language for Adobe Flash Player. The result: I now have the power to create unspeakably irritating advertisement banners, surprisingly fun 2D physics-based games, and various charts of dubious usefulness. In the spirit of sharing, I now give you one of the latter: a [...]]]></description>
			<content:encoded><![CDATA[I&#8217;ve spent the last few months digging deep into ActionScript, the programming language for Adobe Flash Player. The result: I now have the power to create unspeakably irritating advertisement banners, surprisingly fun 2D physics-based games, and various charts of dubious usefulness. In the spirit of sharing, I now give you one of the latter: a smattering of ActionScript benchmarks in colorful, bubbly chart form.
<br /><br />
<a href="/projects/flexbench/index.html">
<img src="/images/flex_bench_v1.png" />
</a>
<br /><br />
This little project was originally inspired by a <a href="http://www.jorendorff.com/articles/javascript/speed-test.html">JavaScript benchmarking page</a> I stumbled across, wherein the author quips &#8220;no one should care about JavaScript performance. But if you do, this page will help you get a feel for which operations are fast and which are slow.&#8221; Pretty much the same rationale applies here &#8211; unless you&#8217;re building a complex, cpu-intensive Flash game (like myself, hence my own interest), you don&#8217;t need to worry too much about outer static variable access taking a few microseconds longer than inner static variable access.
<br /><br />
Usage: click &#8216;Test Iterations&#8217; to perform each benchmarking action the specified number of times. Unless you&#8217;re on a very slow computer, even 150,000 should fly by fairly quick. On some pages, you can also click the &#8216;Auto Test&#8217; button, which will incrementally test more iterations until it has a total duration of at least 100 ms, which should give you a decently accurate average duration (note that the number of iterations may be different for each benchmark). You can also hover over the individual bars to see more detailed statistics and the code performed in the iterations (typically without the loop code itself, with the exception of linked list iteration.) Also, feel free to right-click and select &#8220;View Source&#8221; to look at and/or grab the source code. As usual, the code is licensed under the <a href="http://creativecommons.org/licenses/by-sa/3.0/us/" rel="license">Creative Commons Attribution-Share Alike 3.0 United States License</a>.
<br /><br />
Caveats: I&#8217;m still trying to build a better AxisRenderer so the benchmark groupings look more, er, grouped. The Flex BarChart can group (&#8221;cluster&#8221;) by default, but I haven&#8217;t found a native way to omit empty bars for unequal group sizes or display titles for all group members. Hopefully I&#8217;ll get that figured out soon, along with a staggered benchmarking engine so that you don&#8217;t have to wait for all the benchmarks to complete before the chart updates.
<br /><br />
And naturally, I&#8217;ll be adding some more benchmark variations in the near future. Function calls *are* positively thrilling, after all&#8230;
]]></content:encoded>
			<wfw:commentRss>http://blog.mikelaurence.com/posts/2008/06/flex-benchmarks-are-fun-for-the-whole-family/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails-Style Dynamic Finders For Ruby Arrays</title>
		<link>http://blog.mikelaurence.com/posts/2008/04/rails-style-dynamic-finders-for-ruby-arrays/</link>
		<comments>http://blog.mikelaurence.com/posts/2008/04/rails-style-dynamic-finders-for-ruby-arrays/#comments</comments>
		<pubDate>Wed, 09 Apr 2008 00:37:08 +0000</pubDate>
		<dc:creator>Mike Laurence</dc:creator>
				<category><![CDATA[Capricious Coding]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://mikelaurence.com/?p=13</guid>
		<description><![CDATA[One of my favorite little elegances in Ruby on Rails is ActiveRecord&#8217;s dynamic finder magic. It lets you perform simple model queries with as much readability as is conceivable in a method call:

# Normal ActiveRecord call - tasty, but still a bit bland.
Sandwich.find&#40;:all, :conditions =&#62; &#91;'meat = ? and tastiness = ?', 'turkey', 'medium'&#93;&#41;

# Dynamic [...]]]></description>
			<content:encoded><![CDATA[One of my favorite little elegances in Ruby on Rails is ActiveRecord&#8217;s <a href="http://blog.hasmanythrough.com/2006/8/13/how-dynamic-finders-work">dynamic finder magic</a>. It lets you perform simple model queries with as much readability as is conceivable in a method call:

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># Normal ActiveRecord call - tasty, but still a bit bland.</span><br />
Sandwich.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'meat = ? and tastiness = ?'</span>, <span style="color:#996600;">'turkey'</span>, <span style="color:#996600;">'medium'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
<br />
<span style="color:#008000; font-style:italic;"># Dynamic finder - unequivocally delicious. Try it with chocolate!</span><br />
Sandwich.<span style="color:#9900CC;">find_all_by_meat_and_tastiness</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'bacon'</span>, <span style="color:#996600;">'very'</span><span style="color:#006600; font-weight:bold;">&#41;</span></div></div>

Lost in the wonders of such syntactic saltiness (er, sugariness), I frequently found myself using these kinds of commands on arrays of model objects I had already retrieved from the database. Naturally enough, all I encountered was a variety of colorful exceptions, but I continued to dream of a world where dynamic finders worked for arrays, too.<br /><br />
Fortunately, a little experimentation, a covert glance at the ActiveRecord code, and a timely discovery of the <a href="http://buddingrubyist.wordpress.com/2008/02/05/why-i-like-to-inject/">wonders of inject</a> led me to a successful implementation:
<br />
<br />
<span id="more-13"></span>
<style type="text/css">
  .widget { display:none }
</style>

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC0066; font-weight:bold;">Array</span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># Dynamic finder for Array class</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> method_missing<span style="color:#006600; font-weight:bold;">&#40;</span>method, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># Get method match info; proceed only if a dynamic finder call</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">super</span> <span style="color:#9966CC; font-weight:bold;">unless</span> match = method.<span style="color:#9900CC;">to_s</span>.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">/</span>^find_<span style="color:#006600; font-weight:bold;">&#40;</span>by<span style="color:#006600; font-weight:bold;">|</span>all_by<span style="color:#006600; font-weight:bold;">|</span>index_by<span style="color:#006600; font-weight:bold;">|</span>indices_by<span style="color:#006600; font-weight:bold;">&#41;</span>_<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span>_a<span style="color:#006600; font-weight:bold;">-</span>zA<span style="color:#006600; font-weight:bold;">-</span>Z<span style="color:#006600; font-weight:bold;">&#93;</span>\w<span style="color:#006600; font-weight:bold;">*</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># Determine finder type &amp; attribute names/symbols based on method name</span><br />
&nbsp; &nbsp; finder = match.<span style="color:#9900CC;">captures</span>.<span style="color:#9900CC;">first</span>.<span style="color:#9900CC;">to_sym</span><br />
&nbsp; &nbsp; finder_is_all = <span style="color:#006600; font-weight:bold;">&#40;</span>finder == <span style="color:#ff3333; font-weight:bold;">:all_by</span> <span style="color:#9966CC; font-weight:bold;">or</span> finder == <span style="color:#ff3333; font-weight:bold;">:indices_by</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; attr_names = match.<span style="color:#9900CC;">captures</span>.<span style="color:#9900CC;">last</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'_and_'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; attr_symbols = attr_names.<span style="color:#9900CC;">collect</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>i<span style="color:#006600; font-weight:bold;">|</span> i.<span style="color:#9900CC;">to_sym</span> <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; attr_indices = <span style="color:#006600; font-weight:bold;">&#40;</span>0..<span style="color:#9900CC;">attr_names</span>.<span style="color:#9900CC;">size</span> <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># Iterate through array elements, storing matches as we go (via 'inject')</span><br />
&nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#006600; font-weight:bold;">&#40;</span>0..<span style="color:#9900CC;">size</span><span style="color:#006600; font-weight:bold;">-</span>1<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">inject</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>matches, idx<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; el = <span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#91;</span>idx<span style="color:#006600; font-weight:bold;">&#93;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># Iterate through attribute names and match against hash values (if a hash,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># attempting both string and symbol keys, since we can't distinguish them</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># from the dynamic method) or method names (using __send__)</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> el <span style="color:#9966CC; font-weight:bold;">and</span> attr_indices.<span style="color:#9900CC;">all</span>? <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>attr_idx<span style="color:#006600; font-weight:bold;">|</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#40;</span>el.<span style="color:#9900CC;">is_a</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">Hash</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">and</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;el<span style="color:#006600; font-weight:bold;">&#91;</span>attr_symbols<span style="color:#006600; font-weight:bold;">&#91;</span>attr_idx<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == args<span style="color:#006600; font-weight:bold;">&#91;</span>attr_idx<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;el<span style="color:#006600; font-weight:bold;">&#91;</span>attr_names<span style="color:#006600; font-weight:bold;">&#91;</span>attr_idx<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == args<span style="color:#006600; font-weight:bold;">&#91;</span>attr_idx<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">or</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#40;</span>el.<span style="color:#9900CC;">respond_to</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>attr_symbols<span style="color:#006600; font-weight:bold;">&#91;</span>attr_idx<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">and</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;el.__send__<span style="color:#006600; font-weight:bold;">&#40;</span>attr_symbols<span style="color:#006600; font-weight:bold;">&#91;</span>attr_idx<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> == args<span style="color:#006600; font-weight:bold;">&#91;</span>attr_idx<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># Return first match (or index) unless this is a 'find all' command</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#006600; font-weight:bold;">&#40;</span>finder == <span style="color:#ff3333; font-weight:bold;">:index_by</span> ? idx : el<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> !finder_is_all<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># If 'find all', add element to match array; otherwise, add index</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; matches.<span style="color:#9900CC;">push</span><span style="color:#006600; font-weight:bold;">&#40;</span>finder == <span style="color:#ff3333; font-weight:bold;">:all_by</span> ? el : idx<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">else</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; finder_is_all ? matches : <span style="color:#0000FF; font-weight:bold;">nil</span> &nbsp; <span style="color:#008000; font-style:italic;"># Return state of matches array for 'inject' purposes</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>

I&#8217;m sure there is some ridiculous way to rubyify this into three lines of code, but in the spirit of what this code does (making code prettier), I figured I&#8217;d avoid the obvious <a href="http://www.ioccc.org/">potential for irony</a>.<br /><br />
Much like ActiveRecord&#8217;s dynamic finders, this bit of code accepts find_by and find_all_by methods with any variety of attribute names (as long as they&#8217;re delimited by _and_, e.g. find_by_name_and_age). And while it doesn&#8217;t accept an options hash for miscellaneous conditioning (yet?), it does have a few extras: you can query for the indices of matching elements instead of the elements themselves (e.g., find_index_by_name or find_indices_by_name), and it will match hash key/values in addition to methods.<br /><br />
Some example usage:

<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># Define an array of hashes (with name, birth year, and state entries)</span><br />
hash_citizens = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#123;</span>:name <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Mike'</span>, <span style="color:#ff3333; font-weight:bold;">:birth_year</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> 1982, <span style="color:#ff3333; font-weight:bold;">:state</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:illinois</span><span style="color:#006600; font-weight:bold;">&#125;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color:#006600; font-weight:bold;">&#123;</span>:name <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Barack'</span>, <span style="color:#ff3333; font-weight:bold;">:birth_year</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> 1961, <span style="color:#ff3333; font-weight:bold;">:state</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:illinois</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
<br />
<span style="color:#008000; font-style:italic;"># Define an array of Citizen model objects (with attributes matching entries defined in hashes above)</span><br />
model_citizens = <span style="color:#006600; font-weight:bold;">&#91;</span>Citizen.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Mike'</span>, <span style="color:#ff3333; font-weight:bold;">:birth_year</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> 1982, <span style="color:#ff3333; font-weight:bold;">:state</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:illinois</span><span style="color:#006600; font-weight:bold;">&#41;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Citizen.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Barack'</span>, <span style="color:#ff3333; font-weight:bold;">:birth_year</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> 1961, <span style="color:#ff3333; font-weight:bold;">:state</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:illinois</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
<br />
<span style="color:#008000; font-style:italic;"># Hash key/values will be matched against names supplied in method - :name (or 'name') for find_by_name, etc.</span><br />
<span style="color:#008000; font-style:italic;"># Any other objects will be matched using messages (method calls)</span><br />
hash_citizens.<span style="color:#9900CC;">find_by_name</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'Mike'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
model_citizens.<span style="color:#9900CC;">find_by_name</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'Mike'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
<br />
<span style="color:#008000; font-style:italic;"># Multiple matches will only be returned if 'all' is present in method name</span><br />
model_citizens.<span style="color:#9900CC;">find_by_state</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:illinois</span><span style="color:#006600; font-weight:bold;">&#41;</span> &nbsp; <span style="color:#008000; font-style:italic;"># Returns the first match only</span><br />
model_citizens.<span style="color:#9900CC;">find_all_by_state</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:illinois</span><span style="color:#006600; font-weight:bold;">&#41;</span> &nbsp; <span style="color:#008000; font-style:italic;"># Returns all matches in array, in order</span><br />
<br />
<span style="color:#008000; font-style:italic;"># Indexes are returned similarly</span><br />
model_citizens.<span style="color:#9900CC;">find_index_by_name</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'Barack'</span><span style="color:#006600; font-weight:bold;">&#41;</span> &nbsp; <span style="color:#008000; font-style:italic;"># Returns 1, the position of 'Barack' in the array</span><br />
model_citizens.<span style="color:#9900CC;">find_indices_by_state</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:illinois</span><span style="color:#006600; font-weight:bold;">&#41;</span> &nbsp; <span style="color:#008000; font-style:italic;"># Returns [0,1]</span><br />
<br />
<span style="color:#008000; font-style:italic;"># If no matches are found, returns nil (singular calls) or empty array ('all' calls)</span><br />
model_citizens.<span style="color:#9900CC;">find_by_other_stuff</span> &nbsp; <span style="color:#008000; font-style:italic;"># Returns nil</span><br />
model_citizens.<span style="color:#9900CC;">find_all_by_other_stuff</span> &nbsp; <span style="color:#008000; font-style:italic;"># Returns empty array</span></div></td></tr></tbody></table></div>

I&#8217;ve written 40 or so tests for these routines, so they should work properly enough, but do let me know if you spot any issues. And as always, any other comments or suggestions would also be greatly appreciated!]]></content:encoded>
			<wfw:commentRss>http://blog.mikelaurence.com/posts/2008/04/rails-style-dynamic-finders-for-ruby-arrays/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->