<?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>Dr. Touch &#187; Recipes</title>
	<atom:link href="http://www.drobnik.com/touch/category/recipes/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.drobnik.com/touch</link>
	<description>Bitching and Stiching iPhone Apps (almost) since 1974</description>
	<lastBuildDate>Thu, 02 Sep 2010 13:05:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Backwards Compatibility if Apple Starts Polishing</title>
		<link>http://www.drobnik.com/touch/2010/09/backwards-compatibility-if-apple-starts-polishing/</link>
		<comments>http://www.drobnik.com/touch/2010/09/backwards-compatibility-if-apple-starts-polishing/#comments</comments>
		<pubDate>Thu, 02 Sep 2010 13:00:09 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=3028</guid>
		<description><![CDATA[You can see that Apple is constantly polishing the APIs [...]]]></description>
			<content:encoded><![CDATA[<p>You can see that Apple is constantly polishing the APIs from version to version, but sometimes they make a more drastic change that breaks existing code. Well, not exactly &#8220;breaks&#8221;, but starts to show warnings about you daring to use deprecated methods. </p>
<p>One such change came out of their trying to adhere to their own naming conventions of methods. The second kind of late polishing is if there are new structures introduced without a matching Make macro for easy filling of said structures. I have an example for you, also in CoreLocation.</p>
<p>In this post I&#8217;m exploring two such changes and tell you how I dealt with them in a backwards compatible way.<br />
<span id="more-3028"></span></p>
<h3>A New Make Function</h3>
<p>CoreLocation has a structure CLLocationCoordinate2D which contains latitude and longitude in decimal degrees of any coordinate on Earth. Before 4.0 was introduced I figured that it would be handy to have a CLLocationCoordinate2DMake to go with it, just like you have CGRectMake to create and fill a CGRect.</p>
<p>Turns out, Apple thought so too, and because I guessed the naming convention correctly they introduced this exact method in 4.0 causing my Xcode to complain like this, if I expanded the build results.</p>
<pre>In file included from ../DTFloatingIconView.m:9:
../DTFloatingIconView.h:42: error: static declaration of 'CLLocationCoordinate2DMake' follows non-static declaration
/Developer_Stable/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.0.sdk/System/Library/Frameworks/CoreLocation.framework/Headers/CLLocation.h:125: error: previous declaration of 'CLLocationCoordinate2DMake' was here</pre>
<p>In the code itself you could only see the first line, but the enlightening detail is found right underneath it. There&#8217;s obvious now a &#8220;previous declaration&#8221; of my helper function. It&#8217;s previous to my definition, because it&#8217;s in a header and headers precede your code always. And indeed if we have a look at CLLocation.h, there it is. Clearly marked as not available on Mac and available on iOS as of 4.0:</p>

<div class="wp_codebox"><table><tr id="p30281"><td class="code" id="p3028code1"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">/*
 *  CLLocationCoordinate2DMake:
 *
 *  Discussion:
 *    Returns a new CLLocationCoordinate2D at the given latitude and longitude
 */</span>
CLLocationCoordinate2D CLLocationCoordinate2DMake<span style="color: #002200;">&#40;</span>CLLocationDegrees latitude, CLLocationDegrees longitude<span style="color: #002200;">&#41;</span> __OSX_AVAILABLE_STARTING<span style="color: #002200;">&#40;</span>__MAC_NA,__IPHONE_4_0<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>The question in this case was how I could modify my definition such that I could build with 4.0, targeting 3.0 and above and get no warnings, errors or crashes. Here&#8217;s how:</p>

<div class="wp_codebox"><table><tr id="p30282"><td class="code" id="p3028code2"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#if __IPHONE_OS_VERSION_MAX_ALLOWED &lt; __IPHONE_4_0</span>
<span style="color: #11740a; font-style: italic;">// this method was introduced in SDK 4.0</span>
<span style="color: #a61390;">static</span> inline CLLocationCoordinate2D CLLocationCoordinate2DMake<span style="color: #002200;">&#40;</span>CLLocationDegrees latitude, CLLocationDegrees longitude<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span> 
	CLLocationCoordinate2D coord;
	coord.latitude <span style="color: #002200;">=</span> latitude;
	coord.longitude <span style="color: #002200;">=</span> longitude;
	<span style="color: #a61390;">return</span> coord;
<span style="color: #002200;">&#125;</span>
<span style="color: #6e371a;">#endif</span></pre></td></tr></table></div>

<p>By using the preprocessor macro __IPHONE_OS_VERSION_MAX_ALLOWED I can check the used SDK version and if it is below 4.0 I define it. Marking it as static inline means that this is built into the binary not as function call, but this code is actually inserted into the calling method as if it were local code.</p>
<p>This way I have a function to satisfy the compiler regardless whether I&#8217;m building with SDK 3.x or 4.x. The reason for doing so is that I&#8217;m using this in DTAugmentedRealityController where I don&#8217;t want to force my customers to build with a specific SDK. So that&#8217;s how I implemented it in version 1.1 of the component.</p>
<p>BUT, thinking about it, there&#8217;s a problem when building this code with SDK 4.0 which happily compiles it and omits the new function. But what happens if this runs on a 3.x device? A crash with an unrecognized selector. In debugger you&#8217;d get something like this:</p>
<pre>
dyld: lazy symbol binding failed: Symbol not found: _CLLocationCoordinate2DMake
  Referenced from: /var/mobile/Applications/0E8F890C-F78A-4092-99A5-9466AF298D60/test.app/test
  Expected in: /System/Library/Frameworks/CoreLocation.framework/CoreLocation
</pre>
<p>So how do we make it backwards compatible?</p>
<p>The easiest way I could think of is somewhat brutal, because it involves basically redirecting all calls to my own function. But looking on the bright side, by making it an inline function we actually gain a few nanoseconds by not having to have the function call overhead.</p>

<div class="wp_codebox"><table><tr id="p30283"><td class="code" id="p3028code3"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">static</span> inline CLLocationCoordinate2D CLLocationCoordinate2DInlineMake<span style="color: #002200;">&#40;</span>CLLocationDegrees latitude, CLLocationDegrees longitude<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span> 
	CLLocationCoordinate2D coord;
	coord.latitude <span style="color: #002200;">=</span> latitude;
	coord.longitude <span style="color: #002200;">=</span> longitude;
	<span style="color: #a61390;">return</span> coord;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#define CLLocationCoordinate2DMake CLLocationCoordinate2DInlineMake</span></pre></td></tr></table></div>

<p>This replaces all CLLocationCoordinate2DMake in your code with CLLocationCoordinate2DInlineMake which is an inline function we define regardless of the used SDK or running OS.</p>
<p>It&#8217;s a nasty workaround, but at least it does not cause a crash. And we can keep on using the CLLocationCoordinate2DMake function name. That&#8217;s some consolidation until we can drop 3.x support later this year.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<h3>Renamed Function</h3>
<p>In 3.2 the method of CLLocation getDistanceFrom got renamed to distanceFromLocation. You might wonder why. Simple explanation really, Apple reserves the prefix get for methods that are using one or more of their parameters to return a value in addition to the regular return value. This is generally achieved by passing a pointer (= memory address) to the method which the method then can follow and modify the referenced piece of RAM.</p>
<p>Consider for example the method &#8211; (void)getValue:(void *)buffer of NSValue where the value of NSValue will be copied into the memory pointed to by &#8220;buffer&#8221;. There are very few such methods on the higher level APIs. Many more can be found on the Core Foundation level.</p>
<p>The naming convention seems to go that the first part of the method name tells you what is being returned, namely a distance and the last part before the first colon should tell what this parameter actually is. A name that at the same time tells it&#8217;s function. So they could have called it distanceThatWillBeCalculatedByAVeryComplicatedFormulaAndSoWeNeedASecondParameterThatIsALocation:, as long as the first and the last item in this camel-cased name. The second rule though is to non unnecessarily prolong method names if it&#8217;s possible to get by with 3 or 4 words. A distance from a location, distanceFromLocation. A sorted array by using a selector, sortedArrayUsingSelector.</p>
<p>There are a few such methods in the SDKs that snuck in under the radar of the Naming Convention Adherence Subcommittee at Apple HQ, so they chose to make the switch when introducing 3.2 because at this time that was the first iOS version running on the iPad and thus this change would not cause any problems there. I betcha there was somebody having sleepless nights over this until 3.2 was released in the form of the iPad. Now he can rest in peace.</p>
<p>But to bring balance to the force, somebody being able to rest means that somebody has extra work, we.  Because if we want to keep our code working and warning-free then we have to work around this change.</p>
<p>Since we will be using the latest SDK version for building the new method is valid and the old one is causing a deprecation warning. BUT because we want this code to work on previous iOS versions we cannot exclusively use the distanceFromLocation method, because this would cause an &#8220;unrecognized selector&#8221; exception (read &#8220;crash&#8221;) if somebody is running our app on iOS 3.1.x.</p>
<p>Usually you can work around this by using performSelector after having checked that the instance of the receiver responds to it. But in this case there&#8217;s a problem: we have a return value that we need to get hold of. I found some workarounds on the Internet that would hack and typecast around. But these methods upset my stomach, so I chose to go for the following method.</p>

<div class="wp_codebox"><table><tr id="p30284"><td class="code" id="p3028code4"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CLLocationDistance<span style="color: #002200;">&#41;</span>distanceBetweenLocation<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CLLocation <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>location1 andLocation<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CLLocation <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>location2
<span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>location1 respondsToSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>distanceFromLocation<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>location1 distanceFromLocation<span style="color: #002200;">:</span>location2<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
&nbsp;
	<span style="color: #a61390;">SEL</span> sel <span style="color: #002200;">=</span> <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>getDistanceFrom<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>location1 respondsToSelector<span style="color: #002200;">:</span>sel<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMethodSignature_Class/"><span style="color: #400080;">NSMethodSignature</span></a> <span style="color: #002200;">*</span>mySignature <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CLLocation instanceMethodSignatureForSelector<span style="color: #002200;">:</span>sel<span style="color: #002200;">&#93;</span>;
		<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/"><span style="color: #400080;">NSInvocation</span></a> <span style="color: #002200;">*</span>myInvocation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/"><span style="color: #400080;">NSInvocation</span></a> invocationWithMethodSignature<span style="color: #002200;">:</span>mySignature<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>myInvocation setArgument<span style="color: #002200;">:&amp;</span>location2 atIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">2</span><span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>myInvocation setTarget<span style="color: #002200;">:</span>location1<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>myInvocation setSelector<span style="color: #002200;">:</span>sel<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>myInvocation invoke<span style="color: #002200;">&#93;</span>;
&nbsp;
		CLLocationDistance distance;
		<span style="color: #002200;">&#91;</span>myInvocation getReturnValue<span style="color: #002200;">:&amp;</span>distance<span style="color: #002200;">&#93;</span>;
&nbsp;
		<span style="color: #a61390;">return</span> distance;
	<span style="color: #002200;">&#125;</span>
&nbsp;
	<span style="color: #11740a; font-style: italic;">// should never get here</span>
	<span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Of course this could have been made as a category extension, but I chose not to because I didn&#8217;t want to have to name it distanceBackwardsCompatibleWith3xFromLocation. Reason being, that if you name a category extension method the same as an existing one you overwrite it and there&#8217;s no way (similar to super) to call the original method.</p>
<p>Let me explain the above code. </p>
<p>First location1 is asked if it knows distanceFromLocation, if YES, then this is called and we&#8217;re done.<br />
Then I&#8217;m creating a variable of type SEL to hold the signature (read &#8220;selector&#8221;) of the pre 3.2 method.<br />
At this point I could assume that this has to be present here, but just to be safe I&#8217;m asking again.<br />
Then I&#8217;m building an NSInvocation for this signature and setting as target location1.<br />
I&#8217;m executing the method by calling invoke.<br />
Then I&#8217;m creating a local variable which essentially prompts the compiler to reserve sufficient memory for it.<br />
Finally I&#8217;m retrieving the return value of the invocation.</p>
<p>Do you remember what I said about methods prefixed with &#8220;get&#8221;? That&#8217;s another example: it takes a pointer (which we get by the address operator &#038;) to point to the memory it is allowed to modify. Of course it&#8217;s your responsibility to have sufficient memory space allocated. We know that this method will return a CLLocationDistance (which is really just a double) I can take the above shown shortcut. Otherwise I&#8217;d have to inquire about the size of the return value. Possible, but unnecessary if you know the type.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<h3>Conclusion</h3>
<p>Regardless if it&#8217;s a new convenience function/method or a renaming, as a developer you have to start thinking on several levels at the same time: </p>
<p>1) which methods and functions does my building SDK know about<br />
2) which methods and functions does the executing iOS version know about</p>
<p>Of course you could keep ignoring deprecation warnings, or even go as far as keeping building against an outdated SDK. But your customers expect from you to offer them features that only became available in 4.0. At the same time you still want to get the money from the 3.x crowd. </p>
<p>It boils down to the necessity of having a 3.1 device next to your development Mac just so you can test the backwards compatibility.</p>
<p>So you have to create the compatibility methods, because Apple does not care about backwards compatibility. It&#8217;s in their interest that customers update as soon as possible because this decreases the possibility of jailbreaks.</p>
<p>Fun Fact: NSMakeRange still does not comply with Apple&#8217;s naming conventions (should be called NSRangeMake instead) and they HATE that. <img src='http://www.drobnik.com/touch/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/09/backwards-compatibility-if-apple-starts-polishing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reachability</title>
		<link>http://www.drobnik.com/touch/2010/08/reachability/</link>
		<comments>http://www.drobnik.com/touch/2010/08/reachability/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 15:09:58 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2993</guid>
		<description><![CDATA[If your app requires an internet connection for certain [...]]]></description>
			<content:encoded><![CDATA[<p>If your app requires an internet connection for certain tasks you will have to be able to deal with situations where connectivity drops out for some time. For many cases it might be sufficient to display an error when stringWithContentsOfURL returns nil, but it&#8217;s better customer service to inform the user beforehand. Apple thinks so too, they test all apps also in airplane mode and your app better not crash or confuse the user or else it will get rejected.</p>
<p><img class="alignnone size-full wp-image-2995" title="No Reachability inside" src="http://www.drobnik.com/touch/wp-content/uploads/2010/08/Screen-shot-2010-08-17-at-3.41.04-PM.png" alt="" width="285" height="208" /></p>
<p>Fortunately there is a great sample on the Apple Website that you might have heard it&#8217;s name mentioned in many circles: <a href="http://developer.apple.com/iphone/library/samplecode/Reachability/">Reachability</a>. The first version of this was difficult to use but Apple staff keeps polishing their works and so we have reached version 2.2 already, recently updated for iOS 4. The major change that 2.x gave us is the ability to get continuous updates on connection availability. This enables us to have our apps work similar to the iTunes app which displays a message to this effect when there&#8217;s no connection and has the UI return as soon as the connection is back.</p>
<p><a href="http://www.drobnik.com/touch/wp-content/uploads/2010/08/iTunes_no_internet.jpg"><img class="alignnone size-full wp-image-2994" title="iTunes no internet" src="http://www.drobnik.com/touch/wp-content/uploads/2010/08/iTunes_no_internet.jpg" alt="" width="320" height="480" /></a></p>
<p>So, let&#8217;s explore how to add the source for Reachability to our project and have some live checks.</p>
<p><span id="more-2993"></span></p>
<p>First you need to download the latest version of the sample source from the developer website. Here&#8217;s the <a href="http://developer.apple.com/iphone/library/samplecode/Reachability/">direct link</a>. Click on the &#8220;Download Sample Code&#8221; button to retrieve the ZIP file.</p>
<p>If you open the sample project you might get &#8220;Base SDK missing&#8221; if you&#8217;re using the latest Xcode and SDK beta. Just switch it to one that you have, by going Project &#8211; Edit Project Settings &#8211; Base SDK. I use 4.1 at the time of this writing.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>From the sample project you need Reachability.h and .m, copy them over to your project. The Reachability class actually wraps up functionality available in the SystemConfiguration.framework and so you need to add a reference to that as well.</p>
<p><a href="http://www.drobnik.com/touch/wp-content/uploads/2010/08/Screen-shot-2010-08-17-at-3.53.36-PM.png"><img class="alignnone size-full wp-image-2996" title="File structure with necessary things from sample project" src="http://www.drobnik.com/touch/wp-content/uploads/2010/08/Screen-shot-2010-08-17-at-3.53.36-PM.png" alt="" width="269" height="274" /></a></p>
<p>There are two ways how you can make use of the Reachability class. The synchronous mode lets you query for the current state, the asynchronous mode sends notifications. Usually you&#8217;d want a hybrid solution, because you want a view to look correct for the current network state when it appears as well as react to subsequent changes in reachability. Every instance of Reachability is initialized with a host name that you want to be able to reach.</p>
<p>You can have several running at the same time if your app requires connectivity to seperate hosts. It&#8217;s up to you to decide how likely the second host will not be reachable if the first one isn&#8217;t. Reachability tests if the host name can be resolved and if there is a TCP/IP path that allows to reach the host. It does not check for the availability of certain web pages. So in all likelyhood you get by with just a single Reachability instance. That&#8217;s because not reaching one host usually means that the iPhone does not have internet connectivity.</p>
<p>Here&#8217;s the code to demonstrate the use within a view controller:</p>

<div class="wp_codebox"><table><tr id="p29935"><td class="code" id="p2993code5"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>configureForNetworkStatus<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NetworkStatus<span style="color: #002200;">&#41;</span>status
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// do something with status</span>
	<span style="color: #a61390;">switch</span> <span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span> 
	<span style="color: #002200;">&#123;</span>
		<span style="color: #a61390;">case</span> NotReachable<span style="color: #002200;">:</span>
			NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Not Reachable&quot;</span><span style="color: #002200;">&#41;</span>;
			<span style="color: #a61390;">break</span>;
		<span style="color: #a61390;">case</span> ReachableViaWiFi<span style="color: #002200;">:</span>
			NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Reachable via WiFi&quot;</span><span style="color: #002200;">&#41;</span>;
			<span style="color: #a61390;">break</span>;
		<span style="color: #a61390;">case</span> ReachableViaWWAN<span style="color: #002200;">:</span>
			NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Reachable via WWAN&quot;</span><span style="color: #002200;">&#41;</span>;
			<span style="color: #a61390;">break</span>;
		<span style="color: #a61390;">default</span><span style="color: #002200;">:</span>
			<span style="color: #a61390;">break</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>awakeFromNib
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// subscribe to notification</span>
	<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span> self 
		selector<span style="color: #002200;">:</span> <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>reachabilityChanged<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> 
		name<span style="color: #002200;">:</span> kReachabilityChangedNotification object<span style="color: #002200;">:</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// init one watcher, instance variable</span>
	siteReachability <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Reachability reachabilityWithHostName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;www.apple.com&quot;</span><span style="color: #002200;">&#93;</span>
		 retain<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// get first status</span>
	NetworkStatus siteNetworkStatus <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>siteReachability currentReachabilityStatus<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// do something with it</span>
	<span style="color: #002200;">&#91;</span>self configureForNetworkStatus<span style="color: #002200;">:</span>siteNetworkStatus<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// start continous updates</span>
	<span style="color: #002200;">&#91;</span>siteReachability startNotifier<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>dealloc 
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> removeObserver<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>siteReachability release<span style="color: #002200;">&#93;</span>;  <span style="color: #11740a; font-style: italic;">// also stops notifier</span>
    <span style="color: #002200;">&#91;</span>super dealloc<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> reachabilityChanged<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span style="color: #400080;">NSNotification</span></a><span style="color: #002200;">*</span> <span style="color: #002200;">&#41;</span>note
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// get Reachability instance from notification</span>
	Reachability<span style="color: #002200;">*</span> curReach <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>note object<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// assert that we actually got Reachability instance</span>
	NSParameterAssert<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>curReach isKindOfClass<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>Reachability class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// get current status</span>
	NetworkStatus siteNetworkStatus <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>curReach currentReachabilityStatus<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// do something with it</span>
	<span style="color: #002200;">&#91;</span>self configureForNetworkStatus<span style="color: #002200;">:</span>siteNetworkStatus<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>In this sample I&#8217;m initializing everything in the awakeFromNib because I&#8217;m getting my view controller from a XIB file.</p>
<p>The code shows how to query a fresh instance for the current status. Then it starts the notifier which will send an NSNotification as soon as the connectivity state changes. As you can see there are three different values to NetworkStatus: no connection at all, site reachable via WiFi, site reachable via WWAN (= cellular data). So you could react differently if you know a big pipe is available as opposed to cellular where people might have limited bandwidth or volume.</p>
<p>Checking for reachability of a specific host is the most practical use case of Reachability. In much rarer cases you might want to check for availability of local WiFi or the internet in general (if you don&#8217;t need to access a specific host). Specialized initializers are available for these cases, check the header if you need these.</p>
<p>Enabling your apps for reachability checking is easier than ever. The most difficult part now is to design a nice screen, message or graphic to tell the user that he has to wait until he&#8217;s out of the tunnel.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/08/reachability/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tap&amp;Hold for TableView Cells, Then and Now</title>
		<link>http://www.drobnik.com/touch/2010/08/taphold-for-tableview-cells-then-and-now/</link>
		<comments>http://www.drobnik.com/touch/2010/08/taphold-for-tableview-cells-then-and-now/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 16:06:33 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2963</guid>
		<description><![CDATA[It was before SDK 3.2 that I developed a technique to a [...]]]></description>
			<content:encoded><![CDATA[<p>It was before SDK 3.2 that I developed a technique to add tap-and-hold interactivity to your tableview cells. In this article I&#8217;ll demonstrate the old technique, which still works, and contrast it with how much easier it has become if you can target iOS 3.2 and above.</p>
<p>First the &#8220;old way&#8221;. It needs to customize touch handling for the tableview cells themselves, which means you have to subclass UITableViewCell.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p><span id="more-2963"></span></p>
<p><strong>TouchAndHoldCell.h</strong></p>

<div class="wp_codebox"><table><tr id="p29636"><td class="code" id="p2963code6"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;UIKit/UIKit.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@class</span> TouchAndHoldCell;
&nbsp;
<span style="color: #a61390;">@protocol</span> TouchAndHoldCellDelegate &lt;NSObject&gt;
@optional 
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>didTouchAndHoldForCell<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>TouchAndHoldCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>cell;
<span style="color: #a61390;">@end</span>
&nbsp;
<span style="color: #a61390;">@interface</span> TouchAndHoldCell <span style="color: #002200;">:</span> UITableViewCell 
<span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">id</span> &lt;TouchAndHoldCellDelegate&gt; delegate;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, assign<span style="color: #002200;">&#41;</span> <span style="color: #a61390;">id</span> &lt;TouchAndHoldCellDelegate&gt; delegate;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p><strong>TouchAndHoldCell.m</strong></p>

<div class="wp_codebox"><table><tr id="p29637"><td class="code" id="p2963code7"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;TouchAndHoldCell.h&quot;</span>
&nbsp;
&nbsp;
<span style="color: #a61390;">@implementation</span> TouchAndHoldCell
&nbsp;
<span style="color: #a61390;">@synthesize</span> delegate;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithStyle<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableViewCellStyle<span style="color: #002200;">&#41;</span>style reuseIdentifier<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>reuseIdentifier 
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super initWithStyle<span style="color: #002200;">:</span>style reuseIdentifier<span style="color: #002200;">:</span>reuseIdentifier<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Initialization code</span>
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>touchAndHold<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>params
<span style="color: #002200;">&#123;</span>
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSSet_Class/"><span style="color: #400080;">NSSet</span></a> <span style="color: #002200;">*</span>touches <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>params objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;touches&quot;</span><span style="color: #002200;">&#93;</span>;
	UIEvent <span style="color: #002200;">*</span>event <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>params objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;event&quot;</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>super touchesCancelled<span style="color: #002200;">:</span>touches withEvent<span style="color: #002200;">:</span>event<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>delegate <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">&#91;</span>delegate respondsToSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>didTouchAndHoldForCell<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<span style="color: #002200;">&#91;</span>delegate didTouchAndHoldForCell<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>touchesBegan<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSSet_Class/"><span style="color: #400080;">NSSet</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>touches withEvent<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIEvent <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>event
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// 1 second holding triggers touchAndHOld</span>
	<span style="color: #002200;">&#91;</span>self performSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>touchAndHold<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> withObject<span style="color: #002200;">:</span>
		<span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>touches, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;touches&quot;</span>, event, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;event&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> afterDelay<span style="color: #002200;">:</span><span style="color: #2400d9;">0.5</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>super touchesBegan<span style="color: #002200;">:</span>touches withEvent<span style="color: #002200;">:</span>event<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>touchesMoved<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSSet_Class/"><span style="color: #400080;">NSSet</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>touches withEvent<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIEvent <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>event
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> cancelPreviousPerformRequestsWithTarget<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;	
	<span style="color: #002200;">&#91;</span>super touchesMoved<span style="color: #002200;">:</span>touches withEvent<span style="color: #002200;">:</span>event<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>touchesEnded<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSSet_Class/"><span style="color: #400080;">NSSet</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>touches withEvent<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIEvent <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>event
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> cancelPreviousPerformRequestsWithTarget<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;	
	<span style="color: #002200;">&#91;</span>super touchesEnded<span style="color: #002200;">:</span>touches withEvent<span style="color: #002200;">:</span>event<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>touchesCancelled<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSSet_Class/"><span style="color: #400080;">NSSet</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>touches withEvent<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIEvent <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>event
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> cancelPreviousPerformRequestsWithTarget<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;	
	<span style="color: #002200;">&#91;</span>super touchesCancelled<span style="color: #002200;">:</span>touches withEvent<span style="color: #002200;">:</span>event<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>This works by calling a selector with half a second delay. If the finger is lifted before this expires the delayed call is cancelled. If it does get to expire then we have a long press and thus the cell can tell it&#8217;s delegate (the tableview controller) that a long press (that&#8217;s how Apple calls it) transpired.</p>
<p>To use this you would override the cellForRowAtIndexPath method and provide a method to react to the long press.</p>

<div class="wp_codebox"><table><tr id="p29638"><td class="code" id="p2963code8"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>UITableViewCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView cellForRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #a61390;">static</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>CellIdentifier <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cell&quot;</span>;
&nbsp;
    TouchAndHoldCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>TouchAndHoldCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>tableView dequeueReusableCellWithIdentifier<span style="color: #002200;">:</span>CellIdentifier<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>cell <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>TouchAndHoldCell alloc<span style="color: #002200;">&#93;</span> initWithStyle<span style="color: #002200;">:</span>UITableViewCellStyleDefault reuseIdentifier<span style="color: #002200;">:</span>CellIdentifier<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
		cell.delegate <span style="color: #002200;">=</span> self;
    <span style="color: #002200;">&#125;</span>
&nbsp;
	<span style="color: #11740a; font-style: italic;">// Configure the cell.</span>
	cell.textLabel.text <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Text&quot;</span>;
    <span style="color: #a61390;">return</span> cell;
<span style="color: #002200;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #6e371a;">#pragma mark TouchAndHoldCell Delegate</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>didTouchAndHoldForCell<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>TouchAndHoldCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>cell
<span style="color: #002200;">&#123;</span>
	UIActionSheet <span style="color: #002200;">*</span>action <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIActionSheet alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Actions&quot;</span> delegate<span style="color: #002200;">:</span>self cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cancel&quot;</span> destructiveButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Destruct&quot;</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>action showInView<span style="color: #002200;">:</span>self.view<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>action release<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>actionSheet<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIActionSheet <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>actionSheet didDismissWithButtonIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>buttonIndex
<span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>buttonIndex<span style="color: #002200;">==</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Destruct&quot;</span><span style="color: #002200;">&#41;</span>;
	<span style="color: #002200;">&#125;</span>
	<span style="color: #a61390;">else</span>
	<span style="color: #002200;">&#123;</span>
		NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cancel&quot;</span><span style="color: #002200;">&#41;</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>That&#8217;s the historic evidence of past ingenuity. Next we&#8217;re going to examine how that&#8217;s done today. Easier, faster, more Apple if you will.</p>
<p>iOS and SDK 3.2 gave us one of the most ingenious things that Apple could ever invent. For two years we had to code all our touch handling ourselves which resulted in a variety of different approaches, all with a different feel to them. Gesture Recognizers changed all that, 3.2 brought them first to the iPad and they are also part of iOS 4.x. Unfortunately they are not backwards compatible. </p>
<p>All it takes is to create such a gesture recognizer instance and attach it to the appropriate view.</p>

<div class="wp_codebox"><table><tr id="p29639"><td class="code" id="p2963code9"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>UITableViewCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView 
            cellForRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath 
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">static</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>CellIdentifier <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cell&quot;</span>;
&nbsp;
&nbsp;
    UITableViewCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>tableView dequeueReusableCellWithIdentifier<span style="color: #002200;">:</span>CellIdentifier<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>cell <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> 
	<span style="color: #002200;">&#123;</span>
        cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UITableViewCell alloc<span style="color: #002200;">&#93;</span> initWithStyle<span style="color: #002200;">:</span>UITableViewCellStyleDefault 
		reuseIdentifier<span style="color: #002200;">:</span>CellIdentifier<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
&nbsp;
		UILongPressGestureRecognizer <span style="color: #002200;">*</span>longPressGesture <span style="color: #002200;">=</span> 
			<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UILongPressGestureRecognizer alloc<span style="color: #002200;">&#93;</span> 
			  initWithTarget<span style="color: #002200;">:</span>self action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>longPress<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>cell addGestureRecognizer<span style="color: #002200;">:</span>longPressGesture<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
	<span style="color: #11740a; font-style: italic;">// Configure the cell.</span>
	cell.textLabel.text <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Text&quot;</span>;
    <span style="color: #a61390;">return</span> cell;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>longPress<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UILongPressGestureRecognizer <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>gesture
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// only when gesture was recognized, not when ended</span>
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>gesture.state <span style="color: #002200;">==</span> UIGestureRecognizerStateBegan<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<span style="color: #11740a; font-style: italic;">// get affected cell</span>
		UITableViewCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>UITableViewCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>gesture view<span style="color: #002200;">&#93;</span>;
&nbsp;
		<span style="color: #11740a; font-style: italic;">// get indexPath of cell</span>
		<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span>indexPath <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self.tableView indexPathForCell<span style="color: #002200;">:</span>cell<span style="color: #002200;">&#93;</span>;
&nbsp;
		<span style="color: #11740a; font-style: italic;">// do something with this action</span>
		NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Long-pressed cell at row %d&quot;</span>, indexPath<span style="color: #002200;">&#41;</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Gesture Recognizers employ the same methodology as we have seen before for adding target/actions to UIControls, for example UIButtons. The target is the instance of a class to receive the message, the action is the selector. And the parameter that&#8217;s being passed is the sender of the message. For UIControl events that&#8217;s the sending view, for UIGestureRecognizer events it&#8217;s the instance of the gesture recognizer you have set up.</p>
<p>In the above example we simply create a UILongPressGestureRecognizer (which has the appropriate expiration time interval already built in) and attach it to each cell we create. If the tableview is long enough so that we get to recycle cells it would still work, because we don&#8217;t care which cell a recognizer is attached to, as long as there is one for each cell you can tap on, recycled or new.</p>
<p>In the longPress: method we can query the tableView for the &#8220;line&#8221; we tapped on. For a while I was setting the cell&#8217;s tag value to the number of the row, but I found that this ceases to work if you allow for deletion of rows, because then the indexes you put into the tags have incorrect values. Better to ask the tableView itself at time of the pushing via the conveneient indexPathForCell method.</p>
<p>Also note that this method is being called twice, namely when the gesture is recognized (when the finger was on the cell long enough) and when it&#8217;s ended (when you lift the finger). Usually you&#8217;ll want to only react when it&#8217;s started.</p>
<p>You see, that gesture recognizers really reduce the amount of code we need to write to achieve some advanced touch handling.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/08/taphold-for-tableview-cells-then-and-now/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CGRect Tricks</title>
		<link>http://www.drobnik.com/touch/2010/07/cgrect-tricks/</link>
		<comments>http://www.drobnik.com/touch/2010/07/cgrect-tricks/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 14:57:00 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2763</guid>
		<description><![CDATA[CGRect might just be one of the most often used structu [...]]]></description>
			<content:encoded><![CDATA[<p>CGRect might just be one of the most often used structures that you have in your fingers when coding for iPhone. View frames and bounds are something that you touch way more often than dealing with CGSize or CGPoint values.</p>
<p>So it pays to know about all the nifty utilities that Apple provides for you to make your life easier.</p>
<p><span id="more-2763"></span></p>
<h3>Creating Rectangles</h3>
<p>For most structures that you will encounter in Apple&#8217;s SDKs you will also find a corresponding macro to create such a structure on the fly and in the same line fill it with values. Usually those macros are set up for you as a preprocessor define and are named like the structure they are creating plus suffice Make.</p>

<div class="wp_codebox"><table><tr id="p276310"><td class="code" id="p2763code10"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// create a rectangle</span>
CGRect newRectangle <span style="color: #002200;">=</span> CGRectMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0</span>, <span style="color: #2400d9;">0</span>, <span style="color: #2400d9;">100</span>, <span style="color: #2400d9;">200</span><span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>Actually CGRect consists of two sub-structures, a CGPoint for the (usually) upper left origin as well as a CGSize for the width and height. But CGRectMake takes care of filling these accordingly, the first two parameters go into the origin (x,y) and the latter two parameters end up in size (width, weight). Even though it looks like a C-function it&#8217;s actually not. Due to being configured as preprocessor macro there is no C-function generated at compile time, but actually the commands to fill the structure are copied into your code so you don&#8217;t incur an overhead for pushing the parameters onto the stack and function calling.</p>
<h3>Shrinking, Expanding, Edge Insetting</h3>
<p>If you need to shrink a CGRect by a certain value horizontally and vertically you could do so by modifying the structure members themselves. But way more elegant is to use the provided convenient macro CGRectInset. Positive values will decrease the size evenly for the new rectangle to be centered in the old one. Negative values by the same token will increase it.</p>

<div class="wp_codebox"><table><tr id="p276311"><td class="code" id="p2763code11"><pre class="objc" style="font-family:monospace;">CGRect aRectangle <span style="color: #002200;">=</span> CGRectMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>, <span style="color: #2400d9;">100</span>, <span style="color: #2400d9;">200</span><span style="color: #002200;">&#41;</span>;
CGRect smallerRectangle <span style="color: #002200;">=</span> CGRectInset<span style="color: #002200;">&#40;</span>aRectangle, <span style="color: #2400d9;">10</span>, <span style="color: #2400d9;">20</span><span style="color: #002200;">&#41;</span>;
<span style="color: #11740a; font-style: italic;">// result origin (10, 20) and size (80, 160)</span></pre></td></tr></table></div>

<p>This method is fine for 80% of use cases, but sometimes you want to apply different insets for each edge. Imagine, if you will that you want, to have a property contentInsets that would specify the distance a view content should have from each border. The structure of choice for this is UIEdgeInsets(top, left, bottom, right), and of course, there is also a matching Make macro available. </p>
<p>Once you have both you can easily apply the insets to your rect to receive the finally content rectangle. The macro for this purpose is UIEdgeInsetsInsetRect, would you have guessed?</p>

<div class="wp_codebox"><table><tr id="p276312"><td class="code" id="p2763code12"><pre class="objc" style="font-family:monospace;">CGRect rect <span style="color: #002200;">=</span> CGRectMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0</span>, <span style="color: #2400d9;">0</span>, <span style="color: #2400d9;">100</span>, <span style="color: #2400d9;">200</span><span style="color: #002200;">&#41;</span>;
UIEdgeInsets contentInsets <span style="color: #002200;">=</span> UIEdgeInsetsMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">10</span>, <span style="color: #2400d9;">20</span>, <span style="color: #2400d9;">30</span>, <span style="color: #2400d9;">40</span><span style="color: #002200;">&#41;</span>;
&nbsp;
CGRect result <span style="color: #002200;">=</span> UIEdgeInsetsInsetRect<span style="color: #002200;">&#40;</span>rect, contentInsets<span style="color: #002200;">&#41;</span>;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;x: %f, y: %f, width: %f, height: %f&quot;</span>, 
		result.origin.x, result.origin.y, 
		result.size.width, result.size.height<span style="color: #002200;">&#41;</span>;
<span style="color: #11740a; font-style: italic;">// x: 20.000000, y: 10.000000, width: 40.000000, height: 160.000000</span></pre></td></tr></table></div>

<p>Actually the above NSLog is how I have been inspecting CGRect for the past 2 years. Right after I published the first version of this blog post I was pointed out to me that there is an even more elegant method: NSStringFromCGRect. Wow, a third as much key strokes.</p>

<div class="wp_codebox"><table><tr id="p276313"><td class="code" id="p2763code13"><pre class="objc" style="font-family:monospace;">NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, NSStringFromCGRect<span style="color: #002200;">&#40;</span>result<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>; 
<span style="color: #11740a; font-style: italic;">// {{20, 10}, {40, 160}}</span></pre></td></tr></table></div>

<p>Wway more elegant, I&#8217;m sure you&#8217;ll agree? (Thanks <a href="http://twitter.com/mattfarrugia/status/19915905280">Matt</a> and <a href="http://twitter.com/ashtom/status/19918165422">Thomas</a> But that&#8217;s the point of making these write ups. You learn a bit from writing them and you learn a bit more when other pros tell you the mistakes you made. <img src='http://www.drobnik.com/touch/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Interesting Intersecting</h3>
<p>Another thing that you might want to do often with as little code as possible is to check whether a point is inside a rectangle or whether two rectangle are intersecting each other. Did you hit the rectangle? Did your avatar rectangle intersect with the mine rectangle? Boom!</p>

<div class="wp_codebox"><table><tr id="p276314"><td class="code" id="p2763code14"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// enemy hit?</span>
CGRect enemyRect <span style="color: #002200;">=</span> CGRectMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0</span>, <span style="color: #2400d9;">0</span>, <span style="color: #2400d9;">100</span>, <span style="color: #2400d9;">200</span><span style="color: #002200;">&#41;</span>;
CGPoint hitPoint <span style="color: #002200;">=</span> CGPointMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">50</span>, <span style="color: #2400d9;">50</span><span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>CGRectContainsPoint<span style="color: #002200;">&#40;</span>enemyRect, hitPoint<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// YES!</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// landmine touched?</span>
CGRect playerRect <span style="color: #002200;">=</span> CCRectMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">200</span>, <span style="color: #2400d9;">300</span>, <span style="color: #2400d9;">10</span>, <span style="color: #2400d9;">10</span><span style="color: #002200;">&#41;</span>;
CGRect mineRect <span style="color: #002200;">=</span> CGRectMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">10</span>, <span style="color: #2400d9;">10</span>, <span style="color: #2400d9;">20</span>, <span style="color: #2400d9;">20</span><span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>CGRectIntersectsRect<span style="color: #002200;">&#40;</span>playerRect, mineRect<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// OUCH!</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Doing it like this as opposed to complicated if statements makes your game engine code read almost like plain English. Further similar macros are defined in CGGeometry.h which you can easily look at by CMD+Doubleclicking on such a CGRect macro.</p>
<p>On the WWDC videos I remember seeing the use of for the 4 macros to get the maximum and/or minimum values for the coordinates.  CGRectGetMaxX, CGRectGetMinX, CGRectGetMaxY, CGRectMinY can save you from writing more code than is necessary.</p>
<h3>Dictionary Representation</h3>
<p>Often you might have to store a CGRect in a plist on disk, but you don&#8217;t have to create the dictionary in a difficult fashion. CGRect, being at the same level as Core Foundation has a function to create a CFDictionary for it&#8217;s current contents.</p>

<div class="wp_codebox"><table><tr id="p276315"><td class="code" id="p2763code15"><pre class="objc" style="font-family:monospace;">CFDictionaryRef frameDictRef <span style="color: #002200;">=</span> CGRectCreateDictionaryRepresentation<span style="color: #002200;">&#40;</span>self.view.frame<span style="color: #002200;">&#41;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span>frameDict <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> dictionaryWithDictionary<span style="color: #002200;">:</span>
							   <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>frameDictRef<span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// autoreleased</span>
CFRelease<span style="color: #002200;">&#40;</span>frameDictRef<span style="color: #002200;">&#41;</span>;
&nbsp;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, frameDict<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>You can directly treat the CFDictionary you get back as NSDictionary, but I recommend that you create a new autoreleased instance instead and properly release the CFDictionaryRef. CoreFoundation objects don&#8217;t have an autorelease, that&#8217;s why we have to do it this way to not have a leak.</p>
<pre> {
    Height = 1004;
    Width = 768;
    X = 0;
    Y = 20;
}</pre>
<p>The reverse is way easier because we don&#8217;t have to create something to release afterwards. Just define a CGRect to take up the decoded values and provide the address to it to a function.</p>

<div class="wp_codebox"><table><tr id="p276316"><td class="code" id="p2763code16"><pre class="objc" style="font-family:monospace;">CGRect rect;
CGRectMakeWithDictionaryRepresentation<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>frameDict, <span style="color: #002200;">&amp;</span>amp;rect<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>The same works also for CGPoint and CGSize by the way, but then you naturally get X+Y or Width+Height into your dictionary.</p>
<h3>Storing it in Obj-C Storage Classes</h3>
<p>One more thing I had forgotten about mentioning which comes into play if you are already thinking like an object oriented pro. CGRect are structures, not objects. So you would naturally be out of luck if you wanted to save them in storage classes like NSArray, NSSet or NSDictionary.</p>
<p>How very nice of Apple to provide some class methods in UIGeometry.h that let us wrap all those structures into handy NSObjects.</p>

<div class="wp_codebox"><table><tr id="p276317"><td class="code" id="p2763code17"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span>tmpArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> array<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>tmpArray addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSValue_Class/"><span style="color: #400080;">NSValue</span></a> valueWithCGRect<span style="color: #002200;">:</span>rect<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>tmpArray addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSValue_Class/"><span style="color: #400080;">NSValue</span></a> valueWithCGRect<span style="color: #002200;">:</span>result<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, tmpArray<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>Similar methods are available for points, sizes, transforms and edge insets.</p>
<h3>Conclusion</h3>
<p>You see that a great deal if thinking went into all these convenience methods on our behalf. So that we won&#8217;t have to. This makes working with and manipulating structures that you encounter in your daily Cocoa life a breeze and they should be second nature. So don&#8217;t just store them in your tool chest, but use them sub-consciously. The amount of code you save will take your breath away.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/07/cgrect-tricks/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cells with Switch</title>
		<link>http://www.drobnik.com/touch/2010/07/cells-with-switch/</link>
		<comments>http://www.drobnik.com/touch/2010/07/cells-with-switch/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 17:44:55 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2879</guid>
		<description><![CDATA[When I revisited the settings screen on MyAppSales to a [...]]]></description>
			<content:encoded><![CDATA[<p>When I revisited the <a href="http://www.drobnik.com/touch/2010/07/myappsales-1-0-16/">settings screen on MyAppSales</a> to add a switch it turned my stomach how I would have added it over a year ago versus to the way I&#8217;m doing it now.</p>
<p><a href="http://www.drobnik.com/touch/wp-content/uploads/2010/07/Screen-shot-2010-07-21-at-7.06.25-PM.png"><img src="http://www.drobnik.com/touch/wp-content/uploads/2010/07/Screen-shot-2010-07-21-at-7.06.25-PM.png" alt="" title="MyAppSales Setting Screen" width="320" height="461" class="alignnone size-full wp-image-2883" /></a></p>
<h3>The Old Way</h3>
<p>Consider the following snipped just to get a similar nausea so that you can appreciate what I am going to show you afterwards. That&#8217;s from a random switch in cellForRowAtIndexPath.</p>

<div class="wp_codebox"><table><tr id="p287918"><td class="code" id="p2879code18"><pre class="objc" style="font-family:monospace;"><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>CellIdentifier <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;ServerSectionSwitch&quot;</span>;
&nbsp;
SwitchCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>SwitchCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>tableView dequeueReusableCellWithIdentifier<span style="color: #002200;">:</span>
		CellIdentifier<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>cell <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> 
<span style="color: #002200;">&#123;</span>
	cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>SwitchCell alloc<span style="color: #002200;">&#93;</span> initWithFrame<span style="color: #002200;">:</span>CGRectZero reuseIdentifier<span style="color: #002200;">:</span>
		CellIdentifier<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
cell.titleLabel.text <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Enable on WLAN&quot;</span>;
ASiSTAppDelegate <span style="color: #002200;">*</span>appDelegate <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>ASiSTAppDelegate <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIApplication sharedApplication<span style="color: #002200;">&#93;</span> 
		delegate<span style="color: #002200;">&#93;</span>;
&nbsp;
cell.switchCtl.on <span style="color: #002200;">=</span> appDelegate.serverIsRunning;
<span style="color: #002200;">&#91;</span>cell.switchCtl addTarget<span style="color: #002200;">:</span>appDelegate action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>startStopServer<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> 
			forControlEvents<span style="color: #002200;">:</span>UIControlEventValueChanged<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">return</span> cell;</pre></td></tr></table></div>

<p>So obviously I had created a custom tableview cell, so let&#8217;s glance at that as well.</p>
<p><span id="more-2879"></span></p>
<p><strong>SwitchCell.h</strong></p>

<div class="wp_codebox"><table><tr id="p287919"><td class="code" id="p2879code19"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;UIKit/UIKit.h&gt;</span>
&nbsp;
&nbsp;
<span style="color: #a61390;">@interface</span> SwitchCell <span style="color: #002200;">:</span> UITableViewCell <span style="color: #002200;">&#123;</span>
	UISwitch <span style="color: #002200;">*</span>switchCtl;
	UILabel <span style="color: #002200;">*</span>titleLabel;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> UILabel <span style="color: #002200;">*</span>titleLabel;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> UISwitch <span style="color: #002200;">*</span>switchCtl;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p><strong>SwitchCell.m</strong></p>

<div class="wp_codebox"><table><tr id="p287920"><td class="code" id="p2879code20"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;UIKit/UIKit.h&gt;</span>
&nbsp;
&nbsp;
<span style="color: #a61390;">@interface</span> SwitchCell <span style="color: #002200;">:</span> UITableViewCell <span style="color: #002200;">&#123;</span>
	UISwitch <span style="color: #002200;">*</span>switchCtl;
	UILabel <span style="color: #002200;">*</span>titleLabel;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> UILabel <span style="color: #002200;">*</span>titleLabel;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> UISwitch <span style="color: #002200;">*</span>switchCtl;
&nbsp;
<span style="color: #a61390;">@end</span>
&nbsp;
<span style="color: #6e371a;">#import &quot;SwitchCell.h&quot;</span>
&nbsp;
<span style="color: #6e371a;">#define MAIN_FONT_SIZE 16.0</span>
<span style="color: #6e371a;">#define LEFT_COLUMN_OFFSET 10.0</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> SwitchCell
&nbsp;
<span style="color: #a61390;">@synthesize</span> switchCtl, titleLabel;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithFrame<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGRect<span style="color: #002200;">&#41;</span>frame reuseIdentifier<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>reuseIdentifier <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>self <span style="color: #002200;">=</span> TABLEVIEWCELL_PLAIN_INIT<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Initialization code</span>
		self.selectionStyle <span style="color: #002200;">=</span> UITableViewCellSelectionStyleNone;
&nbsp;
		<span style="color: #11740a; font-style: italic;">// layoutSubViews will decide the final frame</span>
		titleLabel <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UILabel alloc<span style="color: #002200;">&#93;</span> initWithFrame<span style="color: #002200;">:</span>CGRectZero<span style="color: #002200;">&#93;</span>;	
		titleLabel.baselineAdjustment <span style="color: #002200;">=</span> UIBaselineAdjustmentAlignCenters;
		titleLabel.font <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIFont boldSystemFontOfSize<span style="color: #002200;">:</span>MAIN_FONT_SIZE<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>self.contentView addSubview<span style="color: #002200;">:</span>titleLabel<span style="color: #002200;">&#93;</span>;
&nbsp;
		switchCtl <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UISwitch alloc<span style="color: #002200;">&#93;</span> initWithFrame<span style="color: #002200;">:</span>CGRectZero<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>self.contentView addSubview<span style="color: #002200;">:</span>switchCtl<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setSelected<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>selected animated<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>super setSelected<span style="color: #002200;">:</span>selected animated<span style="color: #002200;">:</span>animated<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Configure the view for the selected state</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>layoutSubviews
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>super layoutSubviews<span style="color: #002200;">&#93;</span>;
    CGRect contentRect <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self.contentView bounds<span style="color: #002200;">&#93;</span>;
&nbsp;
	<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>text <span style="color: #002200;">=</span> titleLabel.text;
	CGSize sizeNecessary <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>text sizeWithFont<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIFont systemFontOfSize<span style="color: #002200;">:</span>
		MAIN_FONT_SIZE<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    CGRect frame <span style="color: #002200;">=</span> CGRectMake<span style="color: #002200;">&#40;</span>contentRect.origin.x <span style="color: #002200;">+</span> LEFT_COLUMN_OFFSET , 
		contentRect.origin.y,  sizeNecessary.width<span style="color: #002200;">+</span><span style="color: #2400d9;">20.0</span>,  contentRect.size.height<span style="color: #002200;">&#41;</span>;
	titleLabel.frame <span style="color: #002200;">=</span> frame;
&nbsp;
	frame <span style="color: #002200;">=</span> CGRectMake<span style="color: #002200;">&#40;</span>contentRect.origin.x <span style="color: #002200;">+</span> contentRect.size.width <span style="color: #002200;">-</span> <span style="color: #2400d9;">91.0</span> <span style="color: #002200;">-</span>
		 LEFT_COLUMN_OFFSET,contentRect.origin.y<span style="color: #002200;">+</span>
				<span style="color: #002200;">&#40;</span>contentRect.size.height<span style="color: #002200;">-</span><span style="color: #2400d9;">27.0</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">/</span><span style="color: #2400d9;">2.0</span>, 
					   <span style="color: #2400d9;">94.0</span>, <span style="color: #2400d9;">27.0</span><span style="color: #002200;">&#41;</span>;
	switchCtl.frame <span style="color: #002200;">=</span> frame;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>dealloc 
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>titleLabel release<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>switchCtl release<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>super dealloc<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>Ok, you feel my sickness over this code? Let me explain, these are the reasons why this is crappy coding. </p>
<ul>
<li>It&#8217;s completely unnecessary to make a subclass for UITableViewCell just to add a subview, in this case a UISwitch. This adds so much extra code that it&#8217;s ridiculous. Unmaintainable. Manual. Laughable.</li>
<li>You&#8217;ll laugh out loud (LOL) when you see how I am doing it today and how much less code is necessary. this code completely ignores the cell&#8217;s accessoryView and instead builds it&#8217;s own view hierarchy.</li>
<li>Wasn&#8217;t it SDK 2.1 when we sitched from initWithFrame to initWithStyle?
<li>Obviously I did not know about NSUserDefaults back then, because why else would I save user settings in a &#8220;global&#8221; variable in my app delegate?
<li>Apart from that, I&#8217;m calling an action in a different class, makes it harder to understand for other programmers</li>
<p>But hey, as I said this code is from about 2 years ago. Thankfully I know now better and here I&#8217;m going to share my wisdom. Buckle up!</p>
<h3>The Warp-Speed Way</h3>
<p>First and foremost I don&#8217;t need this extra class any more, because we&#8217;re going to do it using a method that takes care of sizing and positioning of the switch for us automatically.</p>

<div class="wp_codebox"><table><tr id="p287921"><td class="code" id="p2879code21"><pre class="objc" style="font-family:monospace;"><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>CellIdentifier <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;ReportSection3&quot;</span>;
&nbsp;
UITableViewCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>tableView dequeueReusableCellWithIdentifier<span style="color: #002200;">:</span>CellIdentifier<span style="color: #002200;">&#93;</span>;
UISwitch <span style="color: #002200;">*</span>switcher;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>cell <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> 
<span style="color: #002200;">&#123;</span>
	cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UITableViewCell alloc<span style="color: #002200;">&#93;</span> initWithStyle<span style="color: #002200;">:</span>UITableViewCellStyleDefault 
				reuseIdentifier<span style="color: #002200;">:</span>CellIdentifier<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
	switcher <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UISwitch alloc<span style="color: #002200;">&#93;</span> initWithFrame<span style="color: #002200;">:</span>CGRectZero<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>switcher addTarget<span style="color: #002200;">:</span>self action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>toggleSumOnOverview<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
				 forControlEvents<span style="color: #002200;">:</span>UIControlEventValueChanged<span style="color: #002200;">&#93;</span>;
	cell.accessoryView <span style="color: #002200;">=</span> switcher;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">else</span> 
<span style="color: #002200;">&#123;</span>
	switcher <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>UISwitch <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>cell.accessoryView;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// make it multiline 					</span>
cell.textLabel.text <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Fetch royalty sum and<span style="color: #2400d9;">\n</span>show it on overview (slow)&quot;</span>;
cell.textLabel.numberOfLines <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
cell.textLabel.font <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIFont boldSystemFontOfSize<span style="color: #002200;">:</span><span style="color: #2400d9;">13</span><span style="color: #002200;">&#93;</span>;
cell.textLabel.adjustsFontSizeToFitWidth <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// set from user defaults</span>
switcher.on <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> boolForKey<span style="color: #002200;">:</span>
				<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;RoyaltyTotalsOnOverView&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">return</span> cell;</pre></td></tr></table></div>

<p>At the top you see the usual dequeueReusableCellWithIdentifier. Because it&#8217;s special cell with the switch being an addition we give it a new identifier. In case there isn&#8217;t already such a cell we make a new one, create an autoreleased UISwitch and set it as the cell&#8217;s accessoryView.</p>
<p>On the other hand if we got back a cell from the dequeue we set our switcher variable to the accessoryView which has to be a UISwitch, because we put it there. Then I did some adjusting of the text label to fit the long text. Finally the current switch status of the switch is equal to a value in our user defaults.</p>
<p>In short we are getting or creating a switch-enabled cell and set the value of the switch. What&#8217;s great about this approach is that we don&#8217;t have to do anything to position the switch or even find out it&#8217;s correct size. All of this is done automatically. UISwitches know their ideal size (sizeThatFits:) and cells know how to position their accessoryView based on it&#8217;s size. Actually I am convinced that this is the same method Apple uses for whenever you see a switch or any other accessory for that matter in a tableview cell. Another effect you get for free is that if the cell is put into edit mode any textLabel and detailTextLabel will get resized automatically.</p>
<p>The second step, because we no longer call complicated functions to store a user setting somewhere in the app delegate, just reacts to whenever the switch&#8217;s value changes. The <a href="http://www.drobnik.com/touch/2009/02/defaulting-can-be-good/">user defaults mechanism</a> automatically takes care of persisting the changed value and as I have shown recently you can also<a href="http://www.drobnik.com/touch/2010/07/defaults-for-the-defaults/"> easily specify default values</a> for the defaults.</p>

<div class="wp_codebox"><table><tr id="p287922"><td class="code" id="p2879code22"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>toggleSumOnOverview<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UISwitch <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>switcher
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> 
			setBool<span style="color: #002200;">:</span>switcher.on forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;RoyaltyTotalsOnOverView&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Too simple for you? Well, we still need to react to a change of this user setting. So, in the init of the affected viewController all I need to add is:</p>

<div class="wp_codebox"><table><tr id="p287923"><td class="code" id="p2879code23"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// if defaults setting changes</span>
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self 
		selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>reloadTableView<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> 
		name<span style="color: #002200;">:</span>NSUserDefaultsDidChangeNotification object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>This calls a method to reload the contents of its table view whenever any value of the user defaults changes. Of course there needs to be a removeObserver in dealloc as well, but you can imagine this.</p>
<h3>Advanced Tactics</h3>
<p>I love the way Apple lets the cell monitor the size of the accessoryView and take care of all necessary resizing automatically. One scenario where this is especially useful is if you have a purchase button like DTPurchaseButton that enlarges to the left if you push it. Say, in neutral state, the button is labeled $0.99 and if you push it once this changes to BUY NOW. I said it before and I&#8217;ll say it again: the resizing of the textLabel in a tableview cell is done automatically for you!</p>
<p>Take a look at the screenshot below. This has a purchase button as accessoryView in a transparent tableview cell. See how the textLabel automatically decreases its size when the button becomes larger?</p>
<p><img src="http://www.drobnik.com/touch/wp-content/uploads/2010/07/Screen-shot-2010-07-21-at-7.27.27-PM.png" alt="" title="Cell textLabel automatically resizing" width="320" height="96" class="alignnone size-full wp-image-2885" /></p>
<p>This is from a famous Twitter client for which I quite recently implemented In-App Purchasing with my <a href="http://www.drobnik.com/touch/parts-store/">DTShop+DTPurchaseButton</a> killer combo. I will randomly select a winner for a free copy of DTPurchaseButton+DTShop, the easiest way to add IAP to your apps. To enter in the draw, just twitter me the correct answer @dr_touch plus a link to this article before end of July 31st.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/07/cells-with-switch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Defaults for the Defaults</title>
		<link>http://www.drobnik.com/touch/2010/07/defaults-for-the-defaults/</link>
		<comments>http://www.drobnik.com/touch/2010/07/defaults-for-the-defaults/#comments</comments>
		<pubDate>Thu, 15 Jul 2010 10:03:05 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2841</guid>
		<description><![CDATA[I previously explained how to use NSUserDefaults to you [...]]]></description>
			<content:encoded><![CDATA[<p>I previously explained <a href="http://www.drobnik.com/touch/2009/02/defaulting-can-be-good/">how to use NSUserDefaults</a> to your advantage, basically being the OSX equivalent to the Windows registry. User Defaults are the way how you can persist small amounts of data in a convenient way. They are basically dictionaries that the system takes care of for you with the added benefit of being cached in memory.</p>
<p>Today we&#8217;ll up it one notch. Session 124 of the WWDC 2010 videos brought to my attention the fact that there&#8217;s also a mechanism to provide default values for the defaults. Up until now I would have retrieved an object from the defaults, checked if it&#8217;s nil and then set the value. Consider the following code snipped from SpeakerClock:</p>

<div class="wp_codebox"><table><tr id="p284124"><td class="code" id="p2841code24"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> <span style="color: #002200;">*</span>defaults <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span style="color: #400080;">NSNumber</span></a> <span style="color: #002200;">*</span>countdownNum <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>defaults objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Countdown&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>countdownNum<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
	countdown <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>countdownNum doubleValue<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">else</span>
<span style="color: #002200;">&#123;</span>
	countdown <span style="color: #002200;">=</span> self.currentPreset.startDuration;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>This works, but it&#8217;s not elegant. Wouldn&#8217;t it be great if we could pre-register those values so that a simple retrieval always has a result?</p>
<p><span id="more-2841"></span></p>
<p>It turns out that there is not just one set of defaults that you can write to and read from. There are multiple sets, Apple calls them &#8220;domains&#8221;. The one we&#8217;ve been using so far is called the Application Domain and it&#8217;s written to the Library/Preferences folder in you app sandbox. It&#8217;s named like your app bundle identifier with a plist extension. It&#8217;s really just a property list dictionary on disk.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>Other domains available can be either persistant or volatile. Persistant means that they are saved somewhere whereas volatile means that they are only present in memory during the execution of your app. These are all standard domains and they are searched in this order:</p>
<ol>
<li>NSArgumentDomain (volatile)</li>
<li>Application &#8211; Identified by the application’s identifier (persistent)</li>
<li>NSGlobalDomain (persistent)</li>
<li>Languages (Identified by the language names) volatile</li>
<li>NSRegistrationDomain volatile</li>
</ol>
<p>So, we already know the application domain. Languages is set by the system and from these you can get the <a href="http://www.drobnik.com/touch/2009/10/getting-the-users-language/">current UI language</a>. On iPhone all apps are sandboxed, so the global domain is of no use to us. This leaves two potentially useful other domains to explore: the argument domain and the registration domain.</p>
<p>What&#8217;s great about this structure is that we don&#8217;t have to care about accessing these domains specifically. The applicable value is always searched for us. If it&#8217;s not in the application domain, then it&#8217;s taken from the registration domain, if present.</p>
<h3>Using NSRegistrationDomain</h3>
<p>This domain is not written do disk, so you need to fill it with your defaults value every time your app launches. The documentation recommends using the initialize class method which get&#8217;s called only once and before a class is accessed the first time. So let&#8217;s have those in our application delegate.</p>

<div class="wp_codebox"><table><tr id="p284125"><td class="code" id="p2841code25"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> initialize
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// called once before this class is used the first time</span>
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span>defaultsDict <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> dictionaryWithObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Touch&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Doctor&quot;</span><span style="color: #002200;">&#93;</span>;
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> <span style="color: #002200;">*</span>defaults <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>defaults registerDefaults<span style="color: #002200;">:</span>defaultsDict<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>application<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIApplication <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>application didFinishLaunchingWithOptions<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>launchOptions
<span style="color: #002200;">&#123;</span>
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> <span style="color: #002200;">*</span>defaults <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span>;
&nbsp;
	<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>readValue <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>defaults objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Doctor&quot;</span><span style="color: #002200;">&#93;</span>;
	NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;default for key 'Doctor' is '%@'&quot;</span>, readValue<span style="color: #002200;">&#41;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// Override point for customization after app launch</span>
	<span style="color: #002200;">&#91;</span>window addSubview<span style="color: #002200;">:</span>viewController.view<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>window makeKeyAndVisible<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Put all default values for your defaults into the dictionary you pass to the registerDefaults. This enables the mechanism to always find a value and you no longer have to use tricks like I did above to check if a value is actually set.</p>
<p>It makes sense to put all your default values into a dictionary plist that you add to your app bundle. Then instead of creating the dictionary in code to pass to registerDefaults you can read your prepared dictionary from disk and use this. This way you can also easily modify the defaults without having to change your code.</p>
<h3>Arguments</h3>
<p>Something that you probably have less use for on iPhone is the arguments domain because iPhone apps will usually not be called with command line arguments. However if you find yourself leveraging your iPhone app knowledge to create a command line tool in Foundation than that&#8217;s the most convenient method to retrieve parameter values.</p>
<p>For testing you can supply program arguments in Xcode via the Executables section. It also works for iPhone apps, and such arguments override registration or application domain settings. So it&#8217;s great for debugging a setting there.</p>
<p><a href="http://www.drobnik.com/touch/wp-content/uploads/2010/07/Screen-shot-2010-07-15-at-11.45.22.png"><img class="alignnone size-full wp-image-2843" title="Specifying program arguments in Xcode" src="http://www.drobnik.com/touch/wp-content/uploads/2010/07/Screen-shot-2010-07-15-at-11.45.22.png" alt="" width="338" height="247" /></a></p>
<p>The exact same code above now outputs &#8216;Alban&#8217; which was the specified argument. So you override a default setting just to test something without having to add additional code to your project.</p>
<p>For command line tools this replaces the handling of argc and argv in main and gives saves you from having to parse these. As somebody who&#8217;s written a couple of tools let me tell you that this is a big convenience.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p><strong>Conclusion</strong></p>
<p>Actually all of that is explained in the <a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/UserDefaults/UserDefaults.html">Introduction to User Defaults</a> document but for me somebody had to find out which parts actually apply to the iPhone platform. I tend to read over parts that sound too technical and make me think that they probably don&#8217;t work on iPhone.</p>
<p>Knowing about what I wrote here goes a long way to simplifying how your provide default values in your app, how you can quickly override them for testing and how to get arguments from the command line if you chose to write a tool.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/07/defaults-for-the-defaults/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Understanding iOS 4 Backgrounding and Delegate Messaging</title>
		<link>http://www.drobnik.com/touch/2010/07/understanding-ios-4-backgrounding-and-delegate-messaging/</link>
		<comments>http://www.drobnik.com/touch/2010/07/understanding-ios-4-backgrounding-and-delegate-messaging/#comments</comments>
		<pubDate>Sun, 04 Jul 2010 22:05:50 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2787</guid>
		<description><![CDATA[UPDATE: Added handleOpenURL to the flow charts. Added U [...]]]></description>
			<content:encoded><![CDATA[<p>UPDATE: Added handleOpenURL to the flow charts. Added UIApplicationExitsOnSuspend. Untangled some lines.</p>
<p>Now that we all are moving our source code gradually to iOS 4 I had to pause and think a bit about where to move which code. A problem that I&#8217;m facing frequently when updating a project is that the didFinishLaunching is only called if the app really launches.</p>
<p>That poses a bit of a challenge if you are used to doing things like refreshing images or other files off the internet. An app that is resumed from standby does no longer go through this delegate method. So an app that would always show fresh content upon launch before 4.0 multitasking would no longer load any new content as soon as you build it for 4.0. That&#8217;s actually one of the main reasons why I have not yet had time to update MyAppSales to 4.0.</p>
<p>To gain the possibility for &#8220;fast app switching&#8221; you actually don&#8217;t need to do anything. All apps automatically support it because they no longer get terminated if the user pushes the Home button. They get put into a sleep mode while the iPhone still has enough memory for everything else. It&#8217;s only if RAM runs out that the OS starts killing apps. There is begins with the ones that have the most memory reserved.</p>
<p>I grabbed the free trial of <a href="http://www.omnigroup.com/products/omnigraffle/">Omnigraffle</a> and the <a href="http://graffletopia.com/stencils/497">Non-techie Process Flowchart Stencils</a> by gfraser. Then I researched when all these various delegate methods of UIApplication are being called and drew charts to illustrate the flow.</p>
<p>By inhaling first how it was before multitasking and then upgrading your mental process to backgrounding we can begin to fully appreciate how it all fits together.</p>
<p><span id="more-2787"></span><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<h3>The World Before Multitasking</h3>
<p>The first thing that I learned from this is that applicationDidBecomeActive: is being called right after application:didFinishLaunchingWithOptions:. So even before 4.0 it would have been smart to put there any kind of code that you want executed whenever the app becomes active, be it after app start or upon rejecting a phone call.</p>
<p><img class="alignnone size-full wp-image-2817" title="UIApplication Delegate Messaging before MT" src="http://www.drobnik.com/touch/wp-content/uploads/2010/07/UIApplication_Delegate_pre_4_v110.jpg" alt="" width="556" height="767" /></p>
<p>Not shown on this diagram is the situation that your app is eating up all the system memory and ignores both the level 1 and level 2 memory warnings. In that case the OS will also terminate your app without totally unscrupulous.</p>
<p>The mechanism with WillResignActive and DidBecomeActive is sort of the Backgrounding Lite that has always been there. This occurs whenever some other thing is displayed in front of your app. This could be the UI to accept a phone call or something as benign as the synching screen.</p>
<h3>Multitasking ON</h3>
<p>Adding multitasking to this flow chart makes it about twice as complex. I probably spent an hour trying to fit it all together with no crossing lines. Another thing that I noticed while doing this is that applicationWillResignActive: is the only delegate method that I could not optimize into a single box, because one use is to show that the app has been interrupted, the other is to the path into the background.</p>
<p><img class="alignnone size-full wp-image-2818" title="UIApplication Delegate Messaging with MT" src="http://www.drobnik.com/touch/wp-content/uploads/2010/07/UIApplication_Delegate_post_4_v121.jpg" alt="" width="575" height="782" /></p>
<p>An app built with 3.2 will still go through a short background stage where applicationDidEnterBackground: is called. but then it will be terminated as usual. If the same app is built against a 4.x SDK then it will not go straight from background to being terminated. Instead it will stick around and so will be the debugger. As soon as you tap the app icon again or choose it from the app switcher it is first informed that applicationWillEnterForeground and then applicationDidBecomeActive.</p>
<p>An app that is suspended but still in RAM might be terminated by the OS if memory runs low. But after entering the background there is no longer any delegate method being called, instead the app will receive a KILL signal. This occurs also if the user long-presses the app icon in app switcher and then removes the app from there with the removal button.</p>
<p>Accepting a phone call no longer terminates your app but will send it into the appropriate background mode. Within the background box you see two purple states that the app can be in. All apps are suspended in RAM per default. You might want to slim down your memory footprint to make your app a less likely target for killing if the system runs low on memory.</p>
<p>Only apps that actually require background processing continue to be executing. This requirement is either set in info.plist or by telling the OS that you have a task to complete, like for example a file upload.</p>
<p>The following kinds of activities get to run in true multi tasking behind the foreground app with lesser CPU priority.</p>
<ul>
<li>playing music: &#8220;App plays audio&#8221;</li>
<li>geo location: &#8220;App registers for location updates&#8221;</li>
<li>VOIP: &#8220;App provides Voice over IP services&#8221;</li>
</ul>
<p>If your app does one of these things then adding the key to info.plist is all it takes. But be aware that as soon as your app stops doing what it stated it would be doing the OS again will send it to sleep, only to be awakend by another gentle tap by the user.</p>
<p>In background mode you&#8217;re advised to stop updating the UI. Especially with OpenGL Apple is really strict. If you app as much as touches OpenGL while in background the app gets killed right away.</p>
<p>There are only two scenarios left where your app&#8217;s applicationWillTerminate: will actually be called: if it&#8217;s build with an SDK of less than version 4.0 or if you chose to opt out of backgrounding by adding the UIApplicationExitsOnSuspend key to your info.plist.</p>
<p>So, let&#8217;s ask the question we&#8217;ve been doing all this fuss for: Where should you now put your code to initialize, update or save changes? applicationWillTerminate not being called in the majority of cases makes it a rather bad candidate to save user defaults or data.</p>
<p>Looking at the chart I see applicationDidEnterBackground as the ideal candidate delegate method for saving state. This is also the last method to be called before a regular 4.0 app gets put to sleep and before a possible kill.</p>
<p>For updating data from the web the case is not as clear. You would not want to reload every time the user comes back to your app. Possible applicationDidBecomeActive: is a good place, provided that you only reload data if sufficient time has passed to be able to assume that something new is available.</p>
<p>Only the first loading of data can stay in application:didFinishLaunchingWithOptions: since every call  applicationDidBecomeActive: most likely has the data already loaded previously.</p>
<h3>Conclusion</h3>
<p>Adding fast app switching and multitasking support is quite easy since for the most part you don&#8217;t need to do anything. But you WILL have to review the contents of your app delegate methods to see which code has to be moved into one of the other delegate methods now. Clean out applicationWillTerminate: and have a close look at application:didFinishLaunchingWithOptions: to check if you have something in there that needs to be done every time the app becomes active.</p>
<p>These charts come from some experimentation that I did and what I remembered from the WWDC 2010 session videos on multitasking. Potentially there are mistakes or more surprises hidden in there. Please let me know if you find any.</p>
<p>Here&#8217;s the <a href="http://www.drobnik.com/touch/wp-content/uploads/2010/07/UIApplication_Delegate_post_4_v122.pdf">chart in PDF</a> format in case you want to print it out and frame it.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/07/understanding-ios-4-backgrounding-and-delegate-messaging/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>The 3.2 Hurdle of MPMoviePlayerController</title>
		<link>http://www.drobnik.com/touch/2010/07/the-3-2-hurdle-of-mpmovieplayercontroller/</link>
		<comments>http://www.drobnik.com/touch/2010/07/the-3-2-hurdle-of-mpmovieplayercontroller/#comments</comments>
		<pubDate>Sun, 04 Jul 2010 14:20:05 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2783</guid>
		<description><![CDATA[Prior to iOS 3.2 your only option for playing videos on [...]]]></description>
			<content:encoded><![CDATA[<p>Prior to iOS 3.2 your only option for playing videos on iPhone was to use MPMoviePlayerController and only in full screen mode. It made sense because who really wants to look at stamp sized videos on his mobile phone.</p>
<p>The iPad changed all that and brought along several changes in how you can place videos. All those changes also made it into the iPhone SDKs. Here&#8217;s a pitfall that you might not have seen if you didn&#8217;t upgrade the SDK on one of your iPhone projects.<br />
<span id="more-2783"></span><br />
<script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>I had an app that played videos like this:</p>

<div class="wp_codebox"><table><tr id="p278326"><td class="code" id="p2783code26"><pre class="objc" style="font-family:monospace;">movieController <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>MPMoviePlayerController alloc<span style="color: #002200;">&#93;</span> initWithContentURL<span style="color: #002200;">:</span>movieURL<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>movieController play<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>The variable movieController is an instance variable. This is necessary because MPMoviePlayerController could not be released before it&#8217;s done playing without cutting off the video. So I used the notification that it sends upon ending playback to release the object and reclaim the memory.</p>

<div class="wp_codebox"><table><tr id="p278327"><td class="code" id="p2783code27"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// subscribed to MPMoviePlayerPlaybackDidFinishNotification</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> movieFinished<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span style="color: #400080;">NSNotification</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>notification
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>movieController release<span style="color: #002200;">&#93;</span>;
	movieController <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>I want to continue targeting devices with 3.0 and later, but my Xcode only has the 3.2 and 4.0 SDKs. You can build against 4.0 and set deployment target to 3.0. If you use the code above it still builds but confusingly you don&#8217;t get any picture any more, at least not in simulator.</p>
<p>The reason being that MPMoviePlayerController has been modified to output it&#8217;s playback into a UIView. This view is a property you can then incorporate into your own view hierarchy with any dimensions you like. In order to still get the full screen playback you had before you would be required to resort to view adding and controlling and other trickery. But way easier is to instead use the new MPMoviePlayerViewController.</p>
<p>Look again at the class name in case you don&#8217;t see the difference. The &#8220;View&#8221; is new between &#8220;Player&#8221; and &#8220;Controller&#8221;. Note that the name now contains ViewController, so you can present and dismiss it modally like you are used to. MPMoviePlayerViewController takes care of it&#8217;s own MPMoviePlayerController which you can access via a property. The notification still get&#8217;s called if you subscribed to it. So that&#8217;s still a good place to have some actions to execute as soon as video playback finishes.</p>
<p>Now the interesting part: how can you use the new view controller but still have your code working on iPhones which still run 3.x? You have to check if the new class is available and use it only if it can be resolved. If not we need to continue using the old method.</p>

<div class="wp_codebox"><table><tr id="p278328"><td class="code" id="p2783code28"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>NSClassFromString<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;MPMoviePlayerViewController&quot;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
	MPMoviePlayerViewController <span style="color: #002200;">*</span>player <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>MPMoviePlayerViewController alloc<span style="color: #002200;">&#93;</span>
		 initWithContentURL<span style="color: #002200;">:</span>movieURL<span style="color: #002200;">&#93;</span>;
	player.modalTransitionStyle <span style="color: #002200;">=</span> UIModalTransitionStyleCrossDissolve;
	videoOverviewViewController.modalTransitionStyle <span style="color: #002200;">=</span>
		UIModalTransitionStyleCrossDissolve;
	<span style="color: #002200;">&#91;</span>videoOverviewViewController presentModalViewController<span style="color: #002200;">:</span>player animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>player release<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">else</span>
<span style="color: #002200;">&#123;</span>
	 movieController <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>MPMoviePlayerController alloc<span style="color: #002200;">&#93;</span> initWithContentURL<span style="color: #002200;">:</span>movieURL<span style="color: #002200;">&#93;</span>;
	 <span style="color: #002200;">&#91;</span>movieController play<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Here are two interesting things: you can use NSClassFromString to check for runtime availability of classes. Of course the class is available if I build against 4.0 SDK, but when a user legally executes the app on 3.x (due to the lower deployment target) this code detects that the new class is not there. Non-existing classes return nil for NSClassFromString.</p>
<p>Also note that since the modal presenting causes the view controller to be retained we no longer need a special IVAR to keep track of it and can release it locally right after presenting it.</p>
<p>With this small modification I can build my code against the brand new 4.0 SDK but still have it run on iDevices that have not yet been upgraded from 3.x.</p>
<p>Or so I thought. For some reason that I still cannot explain the above code worked fine to play in my iPhone 4, but showed only a black screen on iPhones running 3.1.x. So I called upon Apple Developer Technical Support for a solution, which came a couple of days later. It still had a slight error for using a notification that never got sent, but I fixed that to arrive at the following solution which is now tested and working on 3.1.x, 3.2 and 4.0</p>
<p>In the header:</p>

<div class="wp_codebox"><table><tr id="p278329"><td class="code" id="p2783code29"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// IVARS</span>
MPMoviePlayerViewController <span style="color: #002200;">*</span>mViewPlayer;
MPMoviePlayerController <span style="color: #002200;">*</span>mMPPlayer;</pre></td></tr></table></div>

<p>In the implementation:</p>

<div class="wp_codebox"><table><tr id="p278330"><td class="code" id="p2783code30"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>playVideo<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>url
<span style="color: #002200;">&#123;</span>
	videoOverviewViewController.modalTransitionStyle <span style="color: #002200;">=</span> UIModalTransitionStyleCrossDissolve;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>NSClassFromString<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;MPMoviePlayerController&quot;</span><span style="color: #002200;">&#41;</span> instancesRespondToSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>view<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<span style="color: #11740a; font-style: italic;">// running iOS 3.2 or better</span>
		mViewPlayer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>MPMoviePlayerViewController alloc<span style="color: #002200;">&#93;</span> initWithContentURL<span style="color: #002200;">:</span>url<span style="color: #002200;">&#93;</span>;
		mViewPlayer.modalTransitionStyle <span style="color: #002200;">=</span> UIModalTransitionStyleCrossDissolve;
		videoOverviewViewController.modalTransitionStyle <span style="color: #002200;">=</span> UIModalTransitionStyleCrossDissolve;
&nbsp;
		<span style="color: #002200;">&#91;</span>videoOverviewViewController presentModalViewController<span style="color: #002200;">:</span>mViewPlayer animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
		<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self
				selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>movieDidExitFullscreen<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
				name<span style="color: #002200;">:</span>MPMoviePlayerPlaybackDidFinishNotification
				object<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>mViewPlayer moviePlayer<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
	<span style="color: #a61390;">else</span> 
	<span style="color: #002200;">&#123;</span>
		mMPPlayer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>MPMoviePlayerController alloc<span style="color: #002200;">&#93;</span> initWithContentURL<span style="color: #002200;">:</span>url<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>mMPPlayer play<span style="color: #002200;">&#93;</span>;
&nbsp;
		<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self 
				selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>moviePlayerDidFinish<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
				name<span style="color: #002200;">:</span>MPMoviePlayerPlaybackDidFinishNotification
				object<span style="color: #002200;">:</span>mMPPlayer<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> movieDidExitFullscreen<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span style="color: #400080;">NSNotification</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> aNotification <span style="color: #002200;">&#123;</span>
	MPMoviePlayerController <span style="color: #002200;">*</span>player <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>aNotification object<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span>
	 removeObserver<span style="color: #002200;">:</span>self
	 name<span style="color: #002200;">:</span>MPMoviePlayerPlaybackDidFinishNotification
	 object<span style="color: #002200;">:</span>player<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>player pause<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>player stop<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #002200;">&#91;</span>videoOverviewViewController dismissModalViewControllerAnimated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #002200;">&#91;</span>mViewPlayer.view removeFromSuperview<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>mViewPlayer release<span style="color: #002200;">&#93;</span>;
&nbsp;
	mViewPlayer <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> moviePlayerDidFinish<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span style="color: #400080;">NSNotification</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> aNotification <span style="color: #002200;">&#123;</span>
	MPMoviePlayerController <span style="color: #002200;">*</span>player <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>aNotification object<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span>
	 removeObserver<span style="color: #002200;">:</span>self
	 name<span style="color: #002200;">:</span>MPMoviePlayerPlaybackDidFinishNotification
	 object<span style="color: #002200;">:</span>player<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>player pause<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>player stop<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>player release<span style="color: #002200;">&#93;</span>;
&nbsp;
	mMPPlayer <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>So there you have it, finally an officially recommended way to get full screen video playback working that&#8217;s both backwards compatible with 3.x but gives you the new video features present on 4.0, e.g. portrait playback.</p>
<p>John Muchow also explains how he <a href="http://iphonedevelopertips.com/video/getting-mpmovieplayercontroller-to-cooperate-with-ios4-3-2-ipad-and-earlier-versions-of-iphone-sdk.html">solved this problem on his blog</a>. His approach is slightly different but also quite interesting.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/07/the-3-2-hurdle-of-mpmovieplayercontroller/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Hacking UIScrollView Gesture Recognizers</title>
		<link>http://www.drobnik.com/touch/2010/06/hacking-uiscrollview-gesture-recognizers/</link>
		<comments>http://www.drobnik.com/touch/2010/06/hacking-uiscrollview-gesture-recognizers/#comments</comments>
		<pubDate>Sat, 26 Jun 2010 09:25:30 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2755</guid>
		<description><![CDATA[As of SDK 3.2 most of the touch handling code in stock  [...]]]></description>
			<content:encoded><![CDATA[<p>As of SDK 3.2 most of the touch handling code in stock controls has been taken out and replaced with this amazing new technology called Gesture Recognizers. This means besides of using them yourself and creating your own you can also fiddle with behaviors of standard controls if they interfere with your own gestures.</p>
<p>I&#8217;m currently working quite a bit on something based on UIScrollView and there I found several things that I needed to tweak.</p>
<h3>Disabling Pinch</h3>
<p>The first modification I did was to get around a bug in UIScrollView.  I did not actually want user zooming in my scroll view, but just use the setting of the zoomLevel to scale images without having to redraw them. And you can only set the zoomLevel to values between min and max.</p>
<p>So, during autorotation, I reduced the min zoom scale, set the new zoom level and then set min and max both to the new zoom. But the problem with this, as of SDK 3.2., is that if you change the min or max zoomLevel property the scroll silently adds a UIPinchGestureRecognizer to itself via the addGestureRecognizer method that now all views have.<br />
<span id="more-2755"></span><br />
<script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>Now that in of itself might not be a problem if it did not do anything. But as soon as you pinch the fingers together or apart then there is a bug setting the scrollview&#8217;s contentOffset to (0,0) causing my scrollview to the left and top. So I overrode the addGestureRecognizer to specifically disable the pinch detector.</p>
<p>If you prevent the addition instead of disabling it, you get a crash. Subclass UIScrollView and add this code to the implementation.</p>

<div class="wp_codebox"><table><tr id="p275531"><td class="code" id="p2755code31"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>addGestureRecognizer<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIGestureRecognizer <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>gestureRecognizer
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// workaround for bug: pinch recognizer gets added during rotation,</span>
	<span style="color: #11740a; font-style: italic;">//  causes contentOffset to be set to (0,0) on pinch</span>
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>gestureRecognizer isKindOfClass<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIPinchGestureRecognizer class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		gestureRecognizer.enabled <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
	<span style="color: #002200;">&#125;</span>
&nbsp;
	<span style="color: #002200;">&#91;</span>super addGestureRecognizer<span style="color: #002200;">:</span>gestureRecognizer<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>This way effectively disables the pinching without risking any other adverse effects.</p>
<h3>Perpendicular Swipe Detection</h3>
<p>The second example of fiddling with the scrollview gesture recognizers came from me wanting to use vertical swipes to trigger an action while retaining the horizontal swiping for the scroll view paging.</p>
<p>In my view controller I had this code to add the swipe handling:</p>

<div class="wp_codebox"><table><tr id="p275532"><td class="code" id="p2755code32"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// other init stuff</span>
&nbsp;
	<span style="color: #11740a; font-style: italic;">// add vertical swipe detector</span>
	UISwipeGestureRecognizer <span style="color: #002200;">*</span>swipeRecognizer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UISwipeGestureRecognizer alloc<span style="color: #002200;">&#93;</span> 
		initWithTarget<span style="color: #002200;">:</span>self action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>verticalSwiped<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>self.view addGestureRecognizer<span style="color: #002200;">:</span>swipeRecognizer<span style="color: #002200;">&#93;</span>; 	
	swipeRecognizer.direction <span style="color: #002200;">=</span> UISwipeGestureRecognizerDirectionUp
		 | UISwipeGestureRecognizerDirectionDown;
	swipeRecognizer.delegate <span style="color: #002200;">=</span> self;
	<span style="color: #002200;">&#91;</span>swipeRecognizer release<span style="color: #002200;">&#93;</span>; 
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>With the scrollview behind it it still gets to detect all kinds of swiping also if you swipe diagonally downwards. There&#8217;s an easy way to see what kinds of gestures are currently attached to a view:</p>

<div class="wp_codebox"><table><tr id="p275533"><td class="code" id="p2755code33"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>UIGestureRecognizer <span style="color: #002200;">*</span>gesture <span style="color: #a61390;">in</span> _scrollView.gestureRecognizers<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>gesture requireGestureRecognizerToFail<span style="color: #002200;">:</span>swipeRecognizer<span style="color: #002200;">&#93;</span>;
	NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, gesture<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>All gesture recognizers have a good description and a paging scrollview gets these:</p>
<ul>
<li>UIScrollViewDelayedTouchesBeganGestureRecognizer</li>
<li>UIPanGestureRecognizer, must-fail = UIScrollViewPagingSwipeGestureRecognizer</li>
<li>UIScrollViewPagingSwipeGestureRecognizer, must-fail-for = UIPanGestureRecognizer</li>
</ul>
<p>The pan gesture is the stock one which we also could use, but the two others are custom recognizers that Apple made by subclassing UIGestureRecognizer and added specific detection logic. Now we wouldn&#8217;t want to mess with these, let alone even mention UIScrollViewDelayedTouchesBeganGestureRecognizer or UIScrollViewPagingSwipeGestureRecognizer in our code, because those are private API classes and would cause our app to be rejected.</p>
<p>But again there&#8217;s a simple fix to the dilemma.Note the dependencies must-fail and must-fail-for. In the log you see that for the pan gesture to work, the paging swipe gesture must fail first. This mechanism lets you make gestures dependent on the failure of others or themselves cause others to fail.</p>
<p>We can employ the same mechanism and permit the detection of the paging swipe only if our own vertical swipe gesture failed.</p>

<div class="wp_codebox"><table><tr id="p275534"><td class="code" id="p2755code34"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>UIGestureRecognizer <span style="color: #002200;">*</span>gesture <span style="color: #a61390;">in</span> _scrollView.gestureRecognizers<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// don't want to mention any Apple TM'ed class names ;-)</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>className <span style="color: #002200;">=</span> NSStringFromClass<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>gesture class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>className rangeOfString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Swipe&quot;</span><span style="color: #002200;">&#93;</span>.location<span style="color: #002200;">!=</span>NSNotFound<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<span style="color: #002200;">&#91;</span>gesture requireGestureRecognizerToFail<span style="color: #002200;">:</span>swipeRecognizer<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>I didn&#8217;t want to mess with the two other recognizers because a) I don&#8217;t know what the delayed touches one is for and b) making the pan dependent on the failing of the vertical swipe might introduce a bit of lag for the panning to be detected. So I just got the class name from the instances and made apples paging swipe dependent on my vertical swipe detector failing.</p>
<p>So you see, Gesture Recognizers are not only greatly simplifying touch handling for your apps, but if you dare look at how Apple is using them you can also tweak them a bit if necessary.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/06/hacking-uiscrollview-gesture-recognizers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rendering PDF is easier than you thought</title>
		<link>http://www.drobnik.com/touch/2010/06/rendering-pdf-is-easier-than-you-thought/</link>
		<comments>http://www.drobnik.com/touch/2010/06/rendering-pdf-is-easier-than-you-thought/#comments</comments>
		<pubDate>Thu, 17 Jun 2010 07:54:01 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2718</guid>
		<description><![CDATA[We all know by now that Adobe is almost as evil as ..., [...]]]></description>
			<content:encoded><![CDATA[<p>We all know by now that Adobe is almost as evil as &#8230;, well let&#8217;s say they pioneered a couple of functionalities that where great for the longest time. One being the PDF format which is actually totally built into OSX everywhere. On OSX you&#8217;re able to print into a PDF without having to install extra software. Also iOS comes with PDF support and today we&#8217;ll look at how we can draw a PDF in a view.</p>
<h3>How UIWebView sees it</h3>
<p>The first idea you might have is to use UIWebView to display PDFs which is not difficult, just get the URL, make a NSURLRequest and pass this to a web view.</p>

<div class="wp_codebox"><table><tr id="p271835"><td class="code" id="p2718code35"><pre class="objc" style="font-family:monospace;">_webView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIWebView alloc<span style="color: #002200;">&#93;</span> initWithFrame<span style="color: #002200;">:</span>frame<span style="color: #002200;">&#93;</span>;
_webView.delegate <span style="color: #002200;">=</span> self;
_webView.autoresizingMask <span style="color: #002200;">=</span> UIViewAutoresizingFlexibleWidth | 
	UIViewAutoresizingFlexibleHeight;
&nbsp;
<span style="color: #11740a; font-style: italic;">// we don't want interaction, full size</span>
_webView.scalesPageToFit <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
_webView.userInteractionEnabled <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
_webView.backgroundColor <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIColor whiteColor<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">//fileURL is an NSURL to a PDF file</span>
<span style="color: #002200;">&#91;</span>_webView loadRequest<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLRequest_Class/"><span style="color: #400080;">NSURLRequest</span></a> requestWithURL<span style="color: #002200;">:</span>fileURL<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>But there is one drawback: you cannot really control how it will arrive on screen. For one thing, UIWebView draws a fat gray border and shadow which might somewhat mess up your UI design.</p>
<p>Wouldn&#8217;t it be great if you could draw the PDF somehow into a view? Yes, we can!<br />
<span id="more-2718"></span><br />
<script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<h3>Drawing PDF Pages</h3>
<p>Apple provides in CoreGraphics a whole set of functions prefixed CGPDF to deal with PDFs. The easiest method for drawing the first page of a PDF file I pieced together from the documentation like this. This is a regular view where I replaced the drawRect as follows:</p>

<div class="wp_codebox"><table><tr id="p271836"><td class="code" id="p2718code36"><pre class="objc" style="font-family:monospace;"><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>
	CGContextRef ctx <span style="color: #002200;">=</span> UIGraphicsGetCurrentContext<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// PDF might be transparent, assume white paper</span>
	<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIColor whiteColor<span style="color: #002200;">&#93;</span> set<span style="color: #002200;">&#93;</span>;
	CGContextFillRect<span style="color: #002200;">&#40;</span>ctx, rect<span style="color: #002200;">&#41;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// Flip coordinates</span>
	CGContextGetCTM<span style="color: #002200;">&#40;</span>ctx<span style="color: #002200;">&#41;</span>;
	CGContextScaleCTM<span style="color: #002200;">&#40;</span>ctx, <span style="color: #2400d9;">1</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span>;
	CGContextTranslateCTM<span style="color: #002200;">&#40;</span>ctx, <span style="color: #2400d9;">0</span>, <span style="color: #002200;">-</span>rect.size.height<span style="color: #002200;">&#41;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// url is a file URL</span>
	CGPDFDocumentRef pdf <span style="color: #002200;">=</span> CGPDFDocumentCreateWithURL<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFURLRef<span style="color: #002200;">&#41;</span>url<span style="color: #002200;">&#41;</span>;
	CGPDFPageRef page1 <span style="color: #002200;">=</span> CGPDFDocumentGetPage<span style="color: #002200;">&#40;</span>pdf, <span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// get the rectangle of the cropped inside</span>
	CGRect mediaRect <span style="color: #002200;">=</span> CGPDFPageGetBoxRect<span style="color: #002200;">&#40;</span>page1, kCGPDFCropBox<span style="color: #002200;">&#41;</span>;
	CGContextScaleCTM<span style="color: #002200;">&#40;</span>ctx, rect.size.width <span style="color: #002200;">/</span> mediaRect.size.width,
		rect.size.height <span style="color: #002200;">/</span> mediaRect.size.height<span style="color: #002200;">&#41;</span>;
	CGContextTranslateCTM<span style="color: #002200;">&#40;</span>ctx, <span style="color: #002200;">-</span>mediaRect.origin.x, <span style="color: #002200;">-</span>mediaRect.origin.y<span style="color: #002200;">&#41;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// draw it</span>
	CGContextDrawPDFPage<span style="color: #002200;">&#40;</span>ctx, page1<span style="color: #002200;">&#41;</span>;
	CGPDFDocumentRelease<span style="color: #002200;">&#40;</span>pdf<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>The part about the mediaRect is necessary because PDF pages are typically larger than what you really see on screen. There are usually some printing, color and crop marks outside of the content area. I managed to eliminate those by changing the transformation matrix of the CGContext.</p>
<p>The official method in the documentation is to use CGPDFPageGetDrawingTransform, but this has a catch: it won&#8217;t scale the image to be larger than 100% and instead center it on screen. So we build our own transform, ignoring the aspect ratio because we want to fill the view with that.</p>
<p>If the PDF is small enough to keep in memory you could also load it into an NSData object and access individual pages from it super fast. To read from data as opposed to providing an NSURL you change the code like this:</p>

<div class="wp_codebox"><table><tr id="p271837"><td class="code" id="p2718code37"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// data is an NSData object we filled with the PDF data from file before</span>
CGDataProviderRef dataProvider <span style="color: #002200;">=</span> CGDataProviderCreateWithCFData<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFDataRef<span style="color: #002200;">&#41;</span>data<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
CGPDFDocumentRef pdf <span style="color: #002200;">=</span> CGPDFDocumentCreateWithProvider<span style="color: #002200;">&#40;</span>dataProvider<span style="color: #002200;">&#41;</span>;
CGDataProviderRelease<span style="color: #002200;">&#40;</span>dataProvider<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>We&#8217;re using &#8220;toll-free bridging&#8221; to simply use our NSData instance where the function is expecting a CFDataRef, and of course if we have a method called SomethingCreate then we also have to have a SomethingRelease.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<h3>Conclusion</h3>
<p>Having this ability to render PDF pages int any resolution gives you a great deal of flexibility. A great tool to have in your toolchest! You might even go as far as using PDFs as your main graphics container because it can contain both vector and bitmap graphics. In fact it&#8217;s the closest you can get to vector graphics on iOS.</p>
<p>Now please don&#8217;t go and make yet another PDF reader with this. With iBooks 1.1 soon supporting native PDF viewing that would make no sense.</p>
<p>Here are a couple other ideas:</p>
<ul>
<li>An app that lets you keep your musical note sheets on your iPad. You could mark sections and specify their order and then choose between classical mode (one sheet per screen) or 1-pass mode, where the sections are flattened such that you don&#8217;t have to go back to repeats, but always play from left to right. Couple that with some fancy notes OCR to have the iPad play a bar before you. Maybe use audio clues on when to know to turn the page.</li>
<li>An app that lets you EDIT PDFs on the iPad, with cut/copy/paste support so that you can paste things on the iPad into a PDF-based scrapbook.</li>
<li>Make a presentation app similar to Prezi. You would load a PDF as basis and then you would record zoom levels, viewed rectangle and rotations along a user-defined path. Give presentation to external display.</li>
<li>Use a similar technique to render rich-text documents into reports that you can e-mail from your app.</li>
<li>Make an electronic version of a magazine similar to Wired, no need for Adobe&#8217;s weird Illustrator-to-App converter that makes half a GB apps.</li>
</ul>
<p>If you&#8217;re interesting in partnering or co-developing these ideas please e-mail me.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/06/rendering-pdf-is-easier-than-you-thought/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
