<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Jayway Team Blog » Design Patterns</title>
	
	<link>http://blog.jayway.com</link>
	<description>Sharing Experience</description>
	<pubDate>Wed, 18 Mar 2009 10:13:15 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/jayway/posts/design-patterns" /><feedburner:info uri="jayway/posts/design-patterns" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>UIButton troubles, a better solution</title>
		<link>http://feedproxy.google.com/~r/jayway/posts/design-patterns/~3/_pRQCa1Fyjo/</link>
		<comments>http://blog.jayway.com/2008/12/17/uibutton-troubles-a-better-solution/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 17:10:33 +0000</pubDate>
		<dc:creator>Fredrik Olsson</dc:creator>
		
		<category><![CDATA[Architecture]]></category>

		<category><![CDATA[Design Patterns]]></category>

		<category><![CDATA[Embedded]]></category>

		<category><![CDATA[Frameworks]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[iphone]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[objective-c]]></category>

		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=651</guid>
		<description><![CDATA[I described in my previous post how you can change the class of a live object instance. The use-case was a workaround for bug in Cocoa Touch's UIKit. What if I could fix the bug, instead of applying a work around in my sub-class?
Update: Buttons created with UIButtonTypeRoundedRect is a special case returning a private [...]]]></description>
			<content:encoded><![CDATA[<p>I described in my <a href="http://blog.jayway.com/2008/12/12/uibutton-troubles-and-obj-c-magic/">previous post</a> how you can change the class of a live object instance. The use-case was a workaround for bug in Cocoa Touch's UIKit. What if I could fix the bug, instead of applying a work around in my sub-class?</p>
<p><strong>Update:</strong> Buttons created with <code>UIButtonTypeRoundedRect</code> is a special case returning a private subclass of <code>UIButton</code>, this bugfix can therefor not safely be used with rounded buttons. Good news is that they already have a large nice touch area.</p>
<h3>With Objective-C you can</h3>
<p>In short the problem is that the implementation of the factory method <code>buttonWithType:</code> in <code>UIButton</code> do not respect subclasses, so it will always return instances of <code>UIButton</code>. This is bad since it is the only method available to use to get custom buttons. Without access to the source code for <code>UIButton</code> changes can not be made to the implementation, so in order to fix the bug in UIKit we must wrap the original implementation of <code>buttonWithType:</code> with our own method that applies the bugfix. </p>
<p>Adding a category with a new implementation will not work, since that would shadow the original implementation. What is need is some sort of <a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming">AOP</a>, and Objective-C gives us enough of this but under the name of <a href="http://www.cocoadev.com/index.pl?MethodSwizzling">method-swizzling</a>.</p>
<p>We can intercept method calls to <code>buttonWithType</code>: by swizzling the implementation with the implementation of our own method. In Objective-C all method implementations are called by name, that name is what is know as a selector. By swizzling the implementations we can make messages with the old selector call our new implementation, and vice versa.</p>
<p>We do this by adding a category to UIButton with this class method:</p>
<pre class="objc"><span style="color: #339900;">#import &lt;objc/runtime.h&gt;</span>
+<span style="color: #002200;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #002200;">&#41;</span>load;
<span style="color: #002200;">&#123;</span>
  Method oldMethod = class_getClassMethod<span style="color: #002200;">&#40;</span>self, <span style="color: #0000ff;">@selector</span><span style="color: #002200;">&#40;</span>buttonWithType:<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
  Method newMethod = class_getClassMethod<span style="color: #002200;">&#40;</span>self, <span style="color: #0000ff;">@selector</span><span style="color: #002200;">&#40;</span>__buttonWithType:<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
  method_exchangeImplementations<span style="color: #002200;">&#40;</span>oldMethod, newMethod<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre>
<p>The class method <code>load</code> is called once for each class and category as they are loaded into the run-time, and is the optimal place to add initialization code. Think of it as static initializer blocks in Java.</p>
<p>And that is it, apart from implementing the actual bugfix in our <code>__buttonWithType:</code> method.</p>
<h3>A better bugfix</h3>
<p>The fix I did in my previous post only worked if the new subclass of <code>UIBUtton</code> did not introduce any new instance variables. This is a limitation, and not quite as obvious to new users of our bugfix, so this time around the bugfix will work with any subclass.</p>
<p>The trick here is allocate a new instance of the correct subclass if needed, and copy over the instance variables. Implementation:</p>
<pre class="objc">+<span style="color: #002200;">&#40;</span>UIButton*<span style="color: #002200;">&#41;</span>__buttonWithType:<span style="color: #002200;">&#40;</span>UIButtonType<span style="color: #002200;">&#41;</span>type;
<span style="color: #002200;">&#123;</span>
  UIButton* button = <span style="color: #002200;">&#91;</span>self __buttonWithType:type<span style="color: #002200;">&#93;</span>;
  <span style="color: #0000ff;">Class</span> buttonClass = <span style="color: #002200;">&#91;</span>button <span style="color: #0000ff;">class</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #0000ff;">if</span> <span style="color: #002200;">&#40;</span>button &amp;&amp; buttonClass != self &amp;&amp; buttonClass == <span style="color: #002200;">&#91;</span>UIButton <span style="color: #0000ff;">class</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #0000ff;">size_t</span> oldSize = class_getInstanceSize<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>button <span style="color: #0000ff;">class</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #0000ff;">size_t</span> newSize = class_getInstanceSize<span style="color: #002200;">&#40;</span>self<span style="color: #002200;">&#41;</span>;
    button-&gt;isa = self;
    <span style="color: #0000ff;">if</span> <span style="color: #002200;">&#40;</span>oldSize &lt; newSize<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
      UIButton* newButton = <span style="color: #002200;">&#91;</span>self alloc<span style="color: #002200;">&#93;</span>;
      <a href="http://www.opengroup.org/onlinepubs/009695399/functions/memcpy.html"><span style="color: #0000dd;">memcpy</span></a><span style="color: #002200;">&#40;</span>newButton, button, oldSize<span style="color: #002200;">&#41;</span>;
      button = <span style="color: #002200;">&#91;</span>newButton autorelease<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
  <span style="color: #002200;">&#125;</span>
  <span style="color: #0000ff;">return</span> button;
<span style="color: #002200;">&#125;</span></pre>
<p>At first glance the first statement might look like a recursive call, but remember that we have swizzled the implementations so it will call the original implementation of <code>buttonWithType:</code>.</p>
<p>Also note that we must autorelease the new instance that we allocated, and that we must not release the original instance as that one is already owned by an auto release pool.</p>
<p>And that is how you go about fixing bugs in Objective-C for code that you do not have access to the source code for.</p>
<img src="http://feeds.feedburner.com/~r/jayway/posts/design-patterns/~4/_pRQCa1Fyjo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2008/12/17/uibutton-troubles-a-better-solution/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.jayway.com/2008/12/17/uibutton-troubles-a-better-solution/</feedburner:origLink></item>
	</channel>
</rss>
