<?xml version="1.0" encoding="UTF-8"?>
<!--Generated by Squarespace Site Server v5.11.81 (http://www.squarespace.com/) on Sun, 12 Feb 2012 20:03:44 GMT--><feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><title>Use Your Loaf</title><subtitle>Blog</subtitle><id>http://useyourloaf.com/blog/</id><link rel="alternate" type="application/xhtml+xml" href="http://useyourloaf.com/blog/"/><link rel="self" type="application/atom+xml" href="http://useyourloaf.com/blog/atom.xml"/><updated>2012-02-07T23:49:07Z</updated><generator uri="http://www.squarespace.com/" version="Squarespace Site Server v5.11.81 (http://www.squarespace.com/)">Squarespace</generator><entry><title>Remote Packet Capture for iOS devices</title><category term="ios"/><category term="networking"/><id>http://useyourloaf.com/blog/2012/2/7/remote-packet-capture-for-ios-devices.html</id><link rel="alternate" type="text/html" href="http://useyourloaf.com/blog/2012/2/7/remote-packet-capture-for-ios-devices.html"/><author><name>Keith</name></author><published>2012-02-07T23:33:37Z</published><updated>2012-02-07T23:33:37Z</updated><content type="html" xml:lang="en-GB"><![CDATA[<p>I previously posted about using the <a href="http://useyourloaf.com/blog/2012/1/30/network-link-conditioner.html">Network Link Conditioner</a> to create realistic and &#8220;challenging&#8221; network conditions when testing iOS apps. In this post I want to highlight another useful network debugging tool which allows you capture network traffic from an iOS device.</p>
<h3>Remote Virtual Interfaces</h3>
<p>As with the Network Link Conditioner you need to use a host Mac computer to perform remote packet capture of an iOS device. The only other requirement is that the device be connected to the host computer via USB. No jailbreaking or hacking of your device is required to get this to work.</p>
<p>The basic technique is to create an OS X remote virtual network interface that represents the remote network stack of the iOS device. Once you have the virtual interface you can use your favourite network debugging tool such as tcpdump or wireshark to view the network traffic.</p>
<p>The steps to get the virtual network interface up and running are as follows:</p>
<p>1. Plug your iOS device into the USB port of your Mac.</p>
<p>2. Use the Xcode organizer to obtain the UDID of the device (the value you want is named Identifier):</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-02-07-001.png?__SQUARESPACE_CACHEVERSION=1328657951564" alt="" /></span></span></p>
<p>3. The remote virtual interface is created using the rvictl command, using the UDID you obtained in the previous step. The following command needs to be entered in the terminal window:</p>
<blockquote>
<pre>rvictl -s &lt;UDID&gt;</pre>
</blockquote>
<p>If you want to capture packets from more devices you can repeat this process with the UDID for each device. You can also use the rvictl command to list the active devices:</p>
<blockquote>
<pre>rvictl -l</pre>
</blockquote>
<p>The virtual interfaces are named rvi0, rvi1, rvi2, etc. and like all network interfaces are viewable using the ifconfig command:</p>
<blockquote>
<pre>ifconfig rvi0<br />rvi0: flags=3005&lt;UP,DEBUG,LINK0,LINK1&gt; mtu 0</pre>
</blockquote>
<p>Finally when you are finished you can remove the virtual interface:</p>
<blockquote>
<pre>rvictl -x &lt;UDID&gt;</pre>
</blockquote>
<h3>Using tcpdump</h3>
<p>The easiest way to capture and dump the network traffic is to use the tcpdump command which is included with OS X. The man page for tcpdump has lots of options but if you just want to see the live traffic the following will get you started:</p>
<blockquote>
<pre>tcpdump -n -i rvi0</pre>
</blockquote>
<p>To better illustrate the results I will use the <a href="http://useyourloaf.com/blog/2011/6/16/searching-twitter-with-ios.html">Twitter Search app</a> I showed in an earlier post to generate a simple http request and response.</p>
<blockquote>
<pre>tcpdump -n -t -i rvi0 -q tcp<br />tcpdump: WARNING: rvi0: That device doesn't support promiscuous mode<br />(BIOCPROMISC: Operation not supported on socket)<br />tcpdump: WARNING: rvi0: no IPv4 address assigned<br />tcpdump: verbose output suppressed, use -v or -vv for full protocol decode<br />listening on rvi0, link-type RAW (Raw IP), capture size 65535 bytes<br />IP 192.168.1.66.55101 &gt; 192.168.1.64.51712: tcp 117<br />IP 192.168.1.64.51712 &gt; 192.168.1.66.55101: tcp 0<br />IP 192.168.1.64.51712 &gt; 192.168.1.66.55101: tcp 298<br />IP 192.168.1.66.55101 &gt; 192.168.1.64.51712: tcp 0<br />IP 192.168.1.66.55324 &gt; 199.59.148.201.80: tcp 0<br />IP 199.59.148.201.80 &gt; 192.168.1.66.55324: tcp 0<br />IP 192.168.1.66.55324 &gt; 199.59.148.201.80: tcp 0<br />IP 192.168.1.66.55324 &gt; 199.59.148.201.80: tcp 269<br />IP 199.59.148.201.80 &gt; 192.168.1.66.55324: tcp 0<br />IP 199.59.148.201.80 &gt; 192.168.1.66.55324: tcp 1428<br />IP 199.59.148.201.80 &gt; 192.168.1.66.55324: tcp 1428<br />IP 199.59.148.201.80 &gt; 192.168.1.66.55324: tcp 1428&nbsp;</pre>
</blockquote>
<p>Note the tcpdump options I am using to cut down some of the noise. The -t option gets rid of the timestamp on each line, -q removes some of the packet header information which is not interesting and finally we specify that we are only interested in TCP/IP packets.</p>
<p>My local IP address is 192.168.1.66 and the IP of the remote Twitter server in this case is 199.59.148.201. The http request starts on line 5 where you can see an outgoing connection to port 80:</p>
<blockquote>
<pre style="margin: 8px;">IP 192.168.1.66.55324 &gt; 199.59.148.201.80: tcp 0</pre>
</blockquote>
<p>The following lines show the search results coming back. Of course, this trace is not very interesting as we cannot see the contents. You can add -x to the tcpdump command to see the actual packet contents but even that is not always that informative as you need to know how to decode and interpret the packet data. A quick and dirty way if you know you are dealing with http traffic is to add the -A option to get tcpdump to print the packet data in ASCII:</p>
<blockquote>
<pre>tcpdump -n -t -i rvi0 -q -A tcp<br />...<br />GET /search.json?rpp=100&amp;q=apple HTTP/1.1<br />Host: search.twitter.com<br />User-Agent: TwitterSearch/1.0 CFNetwork/548.0.4 Darwin/11.0.0<br />Accept: */*<br />Accept-Language: en-us<br />Accept-Encoding: gzip, deflate<br />Cookie: k=86.168.77.194.5802087337bc706b<br />Connection: keep-alive<br />...<br />HTTP/1.1 200 OK<br />Cache-Control: max-age=15, must-revalidate, max-age=300<br />Expires: Tue, 07 Feb 2012 22:18:05 GMT<br />Content-Type: application/json;charset=utf-8<br />Vary: Accept-Encoding<br />Date: Tue, 07 Feb 2012 22:13:06 GMT<br />X-Varnish: 682230572<br />Age: 0<br />Via: 1.1 varnish<br />Server: tfe<br />Content-Encoding: gzip<br />Content-Length: 12715&nbsp;</pre>
</blockquote>
<p>This is a minor improvement in that we can now see the HTTP GET request with the query we are using and see the HTTP response but we still cannot easily drop down into the JSON in the result to see what Twitter is sending back. For that we need to use a more sophisticated tool than tcpdump.</p>
<h3>Using Wireshark</h3>
<p>Whilst tcpdump is a quick and easy way to see and capture traffic it is not exactly an easy tool to use when you want to figure out what is going on. <a href="http://www.wireshark.org/">Wireshark</a> is a much easier tool if you want perform deeper packet inspection or if you just prefer your network debugging tools to have a user interface. Luckily Mac OS X ports are readily available, if you are following along I downloaded and installed version 1.6.5 for OS X 10.6 (Snow Leopard) Intel 64-bit from <a href="http://www.wireshark.org/download.html">here</a>.</p>
<p>Once you have Wireshark installed and running you should see a list of available interfaces that it can capture. The one we are interested in is of course our virtual interface rvi0:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-02-07-002.png?__SQUARESPACE_CACHEVERSION=1328658016421" alt="" /></span></span></p>
<p>Selecting rvi0 switches us to a live capture of the packet data with a lot more information to help us decode and understand what is going on. This can be interesting to watch and see all of the things your iOS device is doing. For the purposes of this example it is useful to apply some filters so we can focus in on the HTTP request traffic. The easiest way to do that is to apply a display filter (Analyze -&gt; Display Filters&hellip;). There are a number of pre-defined filter expressions including being able to limit the display to HTTP traffic:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-02-07-003.png?__SQUARESPACE_CACHEVERSION=1328658034464" alt="" /></span></span></p>
<p>Now if create our request it is immediately obvious what is going on as we can clearly see the HTTP GET request and the JSON response:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-02-07-004.png?__SQUARESPACE_CACHEVERSION=1328658055076" alt="" /></span></span></p>
<p>The central pane of wireshark allows you to drill down into the contents of each packet allowing us to see the JSON details:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-02-07-006.png?__SQUARESPACE_CACHEVERSION=1328658072401" alt="" /></span></span><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-02-07-005.png?__SQUARESPACE_CACHEVERSION=1328658098197" alt="" /></span></span></p>
<p>The full packet decode is also available in the lower pane if you need to see the whole packet.</p>
<h3>Wrapping Up</h3>
<p>I should say that this post is not an attempt to explain everything involved in debugging network communications using tcpdump or wireshark. That is a huge topic and requires some knowledge of the underlying protocols. What I did want to make clear is that the tools you need to capture and analyse live traffic off your iOS device are readily available and take just a few minutes to get setup. It is not something you will (hopefully) need to use every day but it is well worth having it in your toolbox for those occasions when you need to debug network communications.</p>
]]></content></entry><entry><title>Network Link Conditioner</title><category term="ios"/><category term="networking"/><id>http://useyourloaf.com/blog/2012/1/30/network-link-conditioner.html</id><link rel="alternate" type="text/html" href="http://useyourloaf.com/blog/2012/1/30/network-link-conditioner.html"/><author><name>Keith</name></author><published>2012-01-30T23:38:51Z</published><updated>2012-01-30T23:38:51Z</updated><content type="html" xml:lang="en-GB"><![CDATA[<p>The Network Link Conditioner (NLC) tool is an extremely useful tool introduced with Lion that allows you to test how well an application behaves when subject to various network conditions. Whilst it is an OS X tool that runs on a Mac it can still be used test iOS apps that are running in the iOS Simulator. In this post I will show some examples of how to use the tool to test an iOS app and verify how it well it handles various network error conditions.</p>
<h3>Getting Up and Running</h3>
<p>With Xcode installed on Lion you should find the NLC tool installed in /Developer/Applications/Utilities/Network Link Conditioner/. It is actually implemented as a System Preferences Pane which you can install with a double-click. The Xcode 4.2 release notes mention a limitation that you need to reboot before the NLC daemon will run or you can manually reload with the following command:</p>
<blockquote>
<p>sudo launchctl load /system/library/launchdaemons/com.apple.networklinkconditioner.plist</p>
</blockquote>
<p>Once installed you should find the Network Link Conditioner icon in the &#8220;Other&#8221; section of the System Preferences pane:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-30-001.png?__SQUARESPACE_CACHEVERSION=1328041120294" alt="" /></span></span></p>
<p>The User Interface is pretty simple, consisting of a master on/off switch, a list of pre-defined profiles and a manage profiles button to create your own profiles. Note that the NLC tool applies to the network interface of your Mac so it will impact ALL traffic on your computer when you turn it on. So you probably want to avoid doing anything else that is relying on a network connection whilst you are testing.</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-30-002.png?__SQUARESPACE_CACHEVERSION=1328041137463" alt="" /></span></span></p>
<p><span style="font-size: 16px; font-weight: bold;">Creating Test Profiles</span></p>
<p>The NLC&nbsp;can be used limit bandwidth, add delays both to normal traffic and to DNS queries and create packet loss. It&nbsp;comes pre-configured with a number of typical network profiles to allow you to simulate common 3G cellular, cable modem, DSL and WiFi connections. For testing purposes I created three rather extreme network conditions as follows:</p>
<h4>Slow Net - Very Limited Bandwidth</h4>
<p>This profile severely limits the bandwidth by setting both the Downlink and Uplink Bandwidth to 32kbps. A 100ms delay is also added to packets in each direction and for good measure there is also a 200ms delay to DNS queries.</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-30-003.png?__SQUARESPACE_CACHEVERSION=1328041165382" alt="" /></span></span></p>
<p>This configuration is useful for slowing down all network communication so that you can really see what your app is doing. This helps flush out any points in your code where you have network code blocking the main thread. It can also help you see any progress bars or temporary spinning activity indicators that might otherwise only be displayed for a split second when testing on a fast network.</p>
<h4>Nasty Net - High Packet Loss</h4>
<p>This network profile increases the pain levels even further by dropping 90% of all packets in each direction:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-30-004.png?__SQUARESPACE_CACHEVERSION=1328041184031" alt="" /></span></span></p>
<h4>Black Hole - 100% Downlink Packet Loss</h4>
<p>Finally I have a network profile which simply drops ALL downlink packets. This is useful for testing network timeout conditions.&nbsp;Try starting with Slow Net and switching to Black Hole once your network traffic gets underway if you really want to be mean&hellip;.</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-30-005.png?__SQUARESPACE_CACHEVERSION=1328041207230" alt="" /></span></span></p>
<h3>Putting an App to the Test</h3>
<p>So to try things out I will run the <a href="http://useyourloaf.com/blog/2011/6/16/searching-twitter-with-ios.html">Twitter Search</a> app that I used to explore NSURLConnection in the iOS Simulator. If you are interested in the code under test refer back to that earlier post for details. The app takes a single string and then uses NSURLConnection to query the Twitter search API and display the results in a table view. Normally when run in the iOS Simulator the results are displayed in under a second which makes it hard to see what is happening. If I turn on the Slow Net profile though the query takes 5-10 seconds making it a lot easier to verify how the app behaves.</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-30-006.png?__SQUARESPACE_CACHEVERSION=1328041228684" alt="" /></span></span></p>
<p>Since we are using an NSURLConnection the actual network connection happens asynchronously, the user interface is not blocked and our table view, displaying a Loading&hellip; message responds to touches. In addition we can see that the network activity spinner has been activated (more on this in a moment) to inform the user that we accessing the network.</p>
<p>To further test what happens when our network connection fails we will switch to the Black Hole profile which will prevent all responses from reaching our app. Now if we wait long enough the network connection should time out and we can test how well we cope with that situation. Our application implements the connection:didFailWithError: delegate method of NSURLConnection to display the error message and we should also see our status message in the first row of the table update to indicate that the service is not available. Sure enough after about a minute the connection times out and the user interface responds correctly:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-30-007.png?__SQUARESPACE_CACHEVERSION=1328041252108" alt="" /></span></span></p>
<p>This is all very good but whilst playing around with this app I actually spotted some unintended behaviour (ok that is another way of saying a bug&hellip;). With either the Slow Net or the Nasty Net profile enabled it is very easy to reproduce. As I mentioned previously whilst we are waiting for the search query to complete so we can display the results the user interface is not blocked. This means that the user can hit the Search button in the Navigation bar to return to the initial screen. When they do that the NSURLConnection is still running and the network activity indicator is still active. Now it will eventually time out and clean itself up but there is nothing to stop the user from initiating another search before the old one has timed out. That is certainly not what I intended when I wrote the app but I never really considered this situation. The fix is easy if we implement the viewWillDisappear method in our view controller and use that to cancel the connection:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">void</span>)viewWillDisappear:(<span style="color: #b80ca1;">BOOL</span>)animated</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #35595d;"><span style="color: #000000;">&nbsp;&nbsp; [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span>cancelConnection<span style="color: #000000;">];</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
</blockquote>
<p>The cancelConnection method takes care of cleaning things up for us:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">void</span>)cancelConnection</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">&nbsp;&nbsp; if</span> (<span style="color: #b80ca1;">self</span>.<span style="color: #538187;">connection</span> != <span style="color: #b80ca1;">nil</span>)</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">&nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">&nbsp;&nbsp;&nbsp; [</span>UIApplication<span style="color: #000000;"> </span><span style="color: #410d80;">sharedApplication</span><span style="color: #000000;">].</span>networkActivityIndicatorVisible<span style="color: #000000;"> = </span><span style="color: #b80ca1;">NO</span><span style="color: #000000;">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">&nbsp;&nbsp;&nbsp; [<span style="color: #b80ca1;">self</span>.<span style="color: #538187;">connection</span> <span style="color: #410d80;">cancel</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">&nbsp;&nbsp;&nbsp; self</span>.<span style="color: #538187;">connection</span> = <span style="color: #b80ca1;">nil</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">&nbsp;&nbsp;&nbsp; self</span>.<span style="color: #538187;">buffer</span> = <span style="color: #b80ca1;">nil</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">&nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
</blockquote>
<p>Now when we exit the search results table view controller any running connection is cancelled, the network activity spinner is stopped and the temporary buffer is cleaned up.</p>
<p><span style="font-size: 16px; font-weight: bold;">Wrapping Up</span></p>
<p>When I started out to write this post I was already sure that testing applications under challenging network conditions was a good idea. However I guess the fact that I actually also found an error in some previously posted code further demonstrates the point. You can find the updated code in my github <a href="https://github.com/kharrison/CodeExamples/tree/master/TwitterSearch">CodeExamples</a> repository.</p>
<p>One final note, don&#8217;t forget to turn NLC off when your done or you may find your Github commits take a bit longer than expected&hellip;.</p>
]]></content></entry><entry><title>Core Data Queries Using Expressions</title><category term="core data"/><category term="ios"/><id>http://useyourloaf.com/blog/2012/1/19/core-data-queries-using-expressions.html</id><link rel="alternate" type="text/html" href="http://useyourloaf.com/blog/2012/1/19/core-data-queries-using-expressions.html"/><author><name>Keith</name></author><published>2012-01-19T22:15:42Z</published><updated>2012-01-19T22:15:42Z</updated><content type="html" xml:lang="en-GB"><![CDATA[<p>Core Data can have a steep learning curve for anybody new to either the Mac or iOS platforms. One of the key points for me was understanding that Core Data is not a relational database but a persistent object store with many features to manage the life-cycle of an object. I think some of the confusion comes from the fact the Core Data can use SQLite as the underlying object store but that is an implementation detail that can lead you astray if you are not careful.</p>
<p>So if Core Data is not a relational database how do you do those things that would be easy if you could just use an SQL query? A Core Data fetch request with a combination of predicates and sort descriptors is a very flexible mechanism that covers many of the most common queries you might need for retrieving objects. However when you are more interested in querying for specific values such as the minimum or maximum value of an attribute an alternative approach using expressions can be easier and more efficient.</p>
<p>To illustrate the code snippets in this post I will assume a very simple Core Data model with a single entity to represent a task in a todo list:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-19-001.png?__SQUARESPACE_CACHEVERSION=1327011563953" alt="" /></span></span></p>
<h3>Retrieving the minimum value of an attribute</h3>
<p>Each task object contains an NSDate attribute which indicates when the task was first created:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;">@property<span style="color: #000000;"> (</span>nonatomic<span style="color: #000000;">, </span>retain<span style="color: #000000;">) </span><span style="color: #7332a8;">NSDate</span><span style="color: #000000;"> * createdAt;</span></p>
</blockquote>
<p>Suppose I want to find out what the oldest creation date is for all of the tasks. A first approach might be to use a fetch request to retrieve the first task after sorting all of the tasks by the creation date (with an ascending sort order):</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSFetchRequest</span> *fetchRequest = [[<span style="color: #7332a8;">NSFetchRequest</span> <span style="color: #410d80;">alloc</span>] <span style="color: #410d80;">init</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;"> </span>NSEntityDescription<span style="color: #000000;"> *entity = [</span>NSEntityDescription<span style="color: #000000;"> </span><span style="color: #410d80;">entityForName</span><span style="color: #000000;">:</span><span style="color: #cc2324;">@&rdquo;Task&rdquo;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;"> inManagedObjectContext</span>:<span style="color: #b80ca1;">self</span>.<span style="color: #538187;">managedObjectContext</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[fetchRequest <span style="color: #410d80;">setEntity</span>:entity];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[fetchRequest <span style="color: #410d80;">setFetchLimit</span>:<span style="color: #3d00d6;">1</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSSortDescriptor</span> *sortDescriptor = [[<span style="color: #7332a8;">NSSortDescriptor</span> <span style="color: #410d80;">alloc</span>] <span style="color: #410d80;">initWithKey</span>:<span style="color: #cc2324;">@&rdquo;createdAt&rdquo;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;"> ascending</span>:<span style="color: #b80ca1;">YES</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[fetchRequest <span style="color: #410d80;">setSortDescriptors</span>:[<span style="color: #7332a8;">NSArray</span> <span style="color: #410d80;">arrayWithObject</span>:sortDescriptor]];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[sortDescriptor <span style="color: #410d80;">release</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSError</span> *error = <span style="color: #b80ca1;">nil</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSArray</span> *fetchResults = [<span style="color: #b80ca1;">self</span>.<span style="color: #538187;">managedObjectContext</span> <span style="color: #410d80;">executeFetchRequest</span>:fetchRequest</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;"> error</span>:&amp;error];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #538187;">Task</span> *oldest = [fetchResults <span style="color: #410d80;">lastObject</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">NSLog</span>(<span style="color: #cc2324;">@&rdquo;oldest = %@&rdquo;</span>,oldest.<span style="color: #538187;">createdAt</span>);</p>
</blockquote>
<p>Note that the fetch limit (setFetchLimit) is set to 1 as we only want the first object in the sorted list of all tasks. This is not a bad solution but as we will see we can do much better. To understand what Core Data is doing under the covers it can be very useful to turn on some debugging. In particular we can get Core Data to show us the underlying SQL queries it is using by setting the argument -com.apple.CoreData.SQLDebug to 1 on application launch. With Xcode 4 the launch arguments are set in the project scheme window:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-19-002.png?__SQUARESPACE_CACHEVERSION=1327011603042" alt="" /></span></span></p>
<p>With the debugging enabled we can see the query that Core Data is using and the fetch execution time which will be useful when comparing the performance of different approaches:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 20:31:37.864 ToDoSync[3455:fb03] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZCOMPLETE, t0.ZCREATEDAT, t0.ZNOTE, t0.ZTITLE FROM ZTASK t0 ORDER BY t0.ZCREATEDAT LIMIT 1</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 20:31:37.875 ToDoSync[3455:fb03] CoreData: annotation: sql connection fetch time: 0.0742s</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 20:31:37.875 ToDoSync[3455:fb03] CoreData: annotation: total fetch execution time: 0.0784s for 1 rows.</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong><br /></strong></p>
<p>The debugging output shows us that Core Data is performing a select to retrieve all of the attributes of the task object, ordered by creation data with a query limit of 1. The total fetch execution time in this case was 0.0784s based on a database containing 5,000 tasks running on a fourth generation iPod touch test device.&nbsp;Note that any time you are looking to optimise performance it is a good advice to run the code on an actual device. Running on the iOS Simulator will give you much faster performance due to the obviously greater performance of the host computer.</p>
<h3>Restricting The Properties to Fetch</h3>
<p>Before looking at the use of expressions there is one minor optimisation that we could consider applying to the previous fetch request. Since we are interested only in the creation date we can modify the fetch request to make it only retrieve that one property:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;"> [fetchRequest </span>setResultType<span style="color: #000000;">:</span>NSDictionaryResultType<span style="color: #000000;">]; </span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;"> [fetchRequest </span>setPropertiesToFetch<span style="color: #000000;">:[</span><span style="color: #7332a8;">NSArray</span><span style="color: #000000;"> </span>arrayWithObject<span style="color: #000000;">:</span><span style="color: #cc2324;">@&rdquo;createdAt&rdquo;</span><span style="color: #000000;">]];</span></p>
</blockquote>
<p>By default the result type of a fetch request is NSManagedObjectResultType which as the name implies means we will get managed objects back from the fetch. To specify that we want one or more properties of an object you first need to make the fetch request return a dictionary by setting the result type to NSDictionaryResultType and then you set the properties to fetch by passing it an array containing the names of the properties you want back. In this case we just want the &ldquo;createdAt&rdquo; property. Now when we execute the fetch request we get back an array containing a single dictionary (since we set a fetch limit of 1) which contains the single property which in this case is an NSDate:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSDate</span> *oldest = [[fetchResults <span style="color: #410d80;">lastObject</span>] <span style="color: #410d80;">valueForKey</span>:<span style="color: #cc2324;">@&rdquo;createdAt&rdquo;</span>]<span style="color: #410d80;">&nbsp;</span></p>
</blockquote>
<p>Looking at the SQL debug you can see that the select statement now only retrieves the single attribute</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 20:59:26.484 ToDoSync[18564:707] CoreData: sql: SELECT t0.ZCREATEDAT FROM ZTASK t0 ORDER BY t0.ZCREATEDAT LIMIT 1</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 20:59:26.535 ToDoSync[18564:707] CoreData: annotation: sql connection fetch time: 0.0505s</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 20:59:26.539 ToDoSync[18564:707] CoreData: annotation: total fetch execution time: 0.0545s for 1 rows.</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong><br /></strong></p>
<p>There is a performance improvement in that this fetch executes in around 0.05s compared to 0.07s for the previous example. However this may often turn out to be a false optimisation if after determining the earliest creation date we then shortly afterwards find we want to retrieve the actual task with this creation date. In that case it is generally better to just retrieve the full task as in the original query so that Core Data already has it cached ready for when we need it.</p>
<h3>Using an Expression</h3>
<p>A better way to solve this type of query is actually to create an expression with the function that we want to perform. Unfortunately there is a little bit more code required though we start as with the previous example by constructing a fetch request that will return a dictionary result:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSFetchRequest</span> *fetchRequest = [[<span style="color: #7332a8;">NSFetchRequest</span> <span style="color: #410d80;">alloc</span>] <span style="color: #410d80;">init</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;"> </span>NSEntityDescription<span style="color: #000000;"> *entity = [</span>NSEntityDescription<span style="color: #000000;"> </span><span style="color: #410d80;">entityForName</span><span style="color: #000000;">:</span><span style="color: #cc2324;">@&rdquo;Task&rdquo;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">inManagedObjectContext</span>:<span style="color: #b80ca1;">self</span>.<span style="color: #538187;">managedObjectContext</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[fetchRequest <span style="color: #410d80;">setEntity</span>:entity];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;"> [fetchRequest </span>setResultType<span style="color: #000000;">:</span>NSDictionaryResultType<span style="color: #000000;">];</span></p>
</blockquote>
<p>We then create an expression which specifies the function we want to use and the key-path of the property we want to apply it to. So for our example where we want the minimum of the createdAt property:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSExpression</span> *keyPathExpression = [<span style="color: #7332a8;">NSExpression</span> <span style="color: #410d80;">expressionForKeyPath</span>:<span style="color: #cc2324;">@&rdquo;createdAt&rdquo;</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSExpression</span> *earliestExpression = [<span style="color: #7332a8;">NSExpression</span> <span style="color: #410d80;">expressionForFunction</span>:<span style="color: #cc2324;">@&rdquo;min:&rdquo;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;"> arguments</span>:[<span style="color: #7332a8;">NSArray</span> <span style="color: #410d80;">arrayWithObject</span>:keyPathExpression]];</p>
</blockquote>
<p>There are a wide range of functions that we could apply including average:, sum:, min:, max:, median:, sqrt:, etc., for the full list check the documentation for the NSExpression class. Unfortunately that is not all we need to do as we must also create an expression description to specify the result type we are expecting from the fetch request:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;"> </span>NSExpressionDescription<span style="color: #000000;"> *earliestExpressionDescription = [[</span>NSExpressionDescription<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span><span style="color: #410d80;">init</span><span style="color: #000000;">];</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[earliestExpressionDescription <span style="color: #410d80;">setName</span>:<span style="color: #cc2324;">@&rdquo;earliestDate&rdquo;</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[earliestExpressionDescription <span style="color: #410d80;">setExpression</span>:earliestExpression];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;"> [earliestExpressionDescription </span>setExpressionResultType<span style="color: #000000;">:</span>NSDateAttributeType<span style="color: #000000;">];</span></p>
</blockquote>
<p>The key point is that we need to set a name for the expression which we will use when retrieving the result - remember that we have already specified that the fetch request should give us back a dictionary containing the result. The name of the expression will be our key into that dictionary. We also need to specify that we expect the result type of the expression to be an NSDate object. Finally we can set the properties to fetch using our expression description and execute the fetch request:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[fetchRequest <span style="color: #410d80;">setPropertiesToFetch</span>:[<span style="color: #7332a8;">NSArray</span> <span style="color: #410d80;">arrayWithObject</span>:earliestExpressionDescription]];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSError</span> *error = <span style="color: #b80ca1;">nil</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSArray</span> *fetchResults = [<span style="color: #b80ca1;">self</span>.<span style="color: #538187;">managedObjectContext</span> <span style="color: #410d80;">executeFetchRequest</span>:fetchRequest</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;"> error</span>:&amp;error];</p>
</blockquote>
<p>The NSArray we get back as the fetch result should contain a single NSDictionary object which contains the NSDate object stored using the expression description name as the key:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSDate</span> *oldest = [[fetchResults <span style="color: #410d80;">lastObject</span>] <span style="color: #410d80;">valueForKey</span>:<span style="color: #cc2324;">@&rdquo;earliestDate&rdquo;</span>];<span style="font-family: Tahoma; font-size: medium;"> </span></p>
</blockquote>
<p>Finally just for completeness and assuming you are not using ARC we should release a few things:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[earliestExpressionDescription <span style="color: #410d80;">release</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[fetchRequest <span style="color: #410d80;">release</span>];</p>
</blockquote>
<p>This is a lot more code than the original solution but the SQL debug log shows some interesting results:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 21:47:39.292 ToDoSync[18639:707] CoreData: sql: SELECT min( t0.ZCREATEDAT) FROM ZTASK t0 </strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 21:47:39.304 ToDoSync[18639:707] CoreData: annotation: sql connection fetch time: 0.0121s</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 21:47:39.308 ToDoSync[18639:707] CoreData: annotation: total fetch execution time: 0.0162s for 1 rows.</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong><br /></strong></p>
<p>I find it somewhat amusing that the more code we write the smaller the underlying Core Data SQLite query gets :-) This fetch request, executed on the same device and dataset as before, executes in 0.0162s which is considerably faster than the original query which took over 0.07s. The reason is obvious if you take a look at the SQL query being used as Core Data is using SQLite to perform the min function directly on the createdAt property in the database avoiding the need to retrieve all 5,000 values.</p>
<p>Where expressions really start to become effective is when you need to perform multiple calculations on the same dataset. So suppose that we want to calculate both the earliest and the latest creation dates. All we need to do is construct a second expression:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSExpression</span> *latestExpression = [<span style="color: #7332a8;">NSExpression</span> <span style="color: #410d80;">expressionForFunction</span>:<span style="color: #cc2324;">@&rdquo;max:&rdquo;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;"> arguments</span>:[<span style="color: #7332a8;">NSArray</span> <span style="color: #410d80;">arrayWithObject</span>:keyPathExpression]];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;"> </span>NSExpressionDescription<span style="color: #000000;"> *latestExpressionDescription = [[</span>NSExpressionDescription<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span><span style="color: #410d80;">init</span><span style="color: #000000;">];</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[latestExpressionDescription <span style="color: #410d80;">setName</span>:<span style="color: #cc2324;">@&rdquo;latestDate&rdquo;</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[latestExpressionDescription <span style="color: #410d80;">setExpression</span>:latestExpression];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;"> [latestExpressionDescription </span>setExpressionResultType<span style="color: #000000;">:</span>NSDateAttributeType<span style="color: #000000;">];</span></p>
</blockquote>
<p>This time we are using the max: function and we have named our expression &ldquo;latestDate&rdquo;. Note that we do not need to use a separate fetch request for each of these expressions. We can set our properties to fetch to include both expressions and execute a single fetch request:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[fetchRequest <span style="color: #410d80;">setPropertiesToFetch</span>:[<span style="color: #7332a8;">NSArray</span> <span style="color: #410d80;">arrayWithObjects</span>:earliestExpressionDescription,</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">latestExpressionDescription, <span style="color: #b80ca1;">nil</span>]];</p>
</blockquote>
<p>Now when we execute the fetch request we get back a dictionary containing two entries representing both the earliestDate and latestDate results:</p>
<blockquote>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSError</span> *error = <span style="color: #b80ca1;">nil</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSArray</span> *fetchResults = [<span style="color: #b80ca1;">self</span>.<span style="color: #538187;">managedObjectContext</span> <span style="color: #410d80;">executeFetchRequest</span>:fetchRequest</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;"> error</span>:&amp;error];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSDate</span> *oldest = [[fetchResults <span style="color: #410d80;">lastObject</span>] <span style="color: #410d80;">valueForKey</span>:<span style="color: #cc2324;">@&rdquo;earliestDate&rdquo;</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSDate</span> *latest = [[fetchResults <span style="color: #410d80;">lastObject</span>] <span style="color: #410d80;">valueForKey</span>:<span style="color: #cc2324;">@&rdquo;latestDate&rdquo;</span>];</p>
</blockquote>
<p>As the SQL debug shows us this query to calculate both the earliest and latest dates executes almost as fast as the fetch for just the earliest date and is still many times faster than the original approach of sorting the property with Core Data:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 22:06:33.153 ToDoSync[18681:707] CoreData: sql: SELECT min( t0.ZCREATEDAT), max( t0.ZCREATEDAT) FROM ZTASK t0 </strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 22:06:33.170 ToDoSync[18681:707] CoreData: annotation: sql connection fetch time: 0.0174s</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><strong>2012-01-19 22:06:33.175 ToDoSync[18681:707] CoreData: annotation: total fetch execution time: 0.0220s for 1 rows.</strong></p>
<h3>Wrapping Up</h3>
<p>Using NSExpression is perhaps not the most intuitive way to perform complex queries and calculations on Core Data sets. However I think it is worth spending some time mastering them as the performance improvements can be significant, especially when you need to frequently repeat a calculation with a large data set.</p>
]]></content></entry><entry><title>Xcode 4.2 building for iOS 3.1.x and older devices</title><category term="ios"/><category term="xcode"/><id>http://useyourloaf.com/blog/2012/1/10/xcode-42-building-for-ios-31x-and-older-devices.html</id><link rel="alternate" type="text/html" href="http://useyourloaf.com/blog/2012/1/10/xcode-42-building-for-ios-31x-and-older-devices.html"/><author><name>Keith</name></author><published>2012-01-10T22:44:08Z</published><updated>2012-01-10T22:44:08Z</updated><content type="html" xml:lang="en-GB"><![CDATA[<p>the extra effort it takes to maintain backward compatibility with iOS 3.1.x is getting a little greater with each update to Xcode and iOS. The release of Xcode 4.2 and iOS 5 added a couple of extra hurdles if you want to support older devices and pre-iOS 4.2 releases.</p>
<h3>Xcode iOS Simulator and Debugging Support</h3>
<p>When Apple released iOS 5 and Xcode 4.2 they removed iOS Simulator support for iOS versions prior to iOS 4.3. If you upgraded from an earlier version of Xcode you may not have noticed but they also made the iOS 4.3 simulator an optional download. If you do not see the iOS 4.3 simulator in the run destination popup you need to use the More Simulators option to download it.</p>
<p>Since the simulator no longer supports iOS versions prior to iOS 4.3 the only way to test apps on those earlier releases is to test on a device. That assumes of course that you still have a device running the iOS 3.1, 4.1 or 4.2 release that you need.</p>
<p>There is an additional step required if you are targeting iOS 3.1 or iOS 4.1 devices in that you also need to download the device debugging support. There are separate installs for iOS 4.x and iOS 3.x devices.&nbsp;When you plug in a development device running a pre-iOS 4.2 version you get prompted to download the appropriate package:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-10-001.png?__SQUARESPACE_CACHEVERSION=1326235784465" alt="" /></span></span></p>
<p>You can also check and install the packages from the Downloads tab of the Xcode preferences:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-10-002.png?__SQUARESPACE_CACHEVERSION=1326235813577" alt="" /></span></span></p>
<p><span style="font-size: 16px; font-weight: bold;">Building for armv6 Devices</span></p>
<p>Having got all the optional Xcode support files downloaded you may think you are done but if you build and run on older armv6 devices you may still hit a problem. Typically the build succeeds but fails to launch on the device. The problem is&nbsp;with older armv6 devices such as the second generation iPod touch and the iPhone 3G.</p>
<p>The default for iOS is now armv7 - otherwise referred to as $(ARCHS_STANDARD_32_BIT). To build for the older devices you need to add armv6 to the Architectures build setting. The default in Xcode 4.2 is now as shown below:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-10-003.png?__SQUARESPACE_CACHEVERSION=1326235835678" alt="" /></span></span></p>
<p>To add armv6 select the existing architecture setting and then using &#8220;Other&hellip;&#8221; to bring up the dialog and add an entry with the value &#8220;armv6 armv7&#8221; to return to building the &#8220;fat&#8221; binary. Ensure you do this for each target in the project. The setting should look as follows once you are done:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2012/2012-01-10-004.png?__SQUARESPACE_CACHEVERSION=1326235862348" alt="" /></span></span></p>
<p>Now you should finally be able to build and run on pre iOS 4.2 devices.</p>
]]></content></entry><entry><title>UIStepper control</title><category term="UIKit"/><category term="ios"/><category term="ios 5"/><id>http://useyourloaf.com/blog/2012/1/4/uistepper-control.html</id><link rel="alternate" type="text/html" href="http://useyourloaf.com/blog/2012/1/4/uistepper-control.html"/><author><name>Keith</name></author><published>2012-01-04T21:07:26Z</published><updated>2012-01-04T21:07:26Z</updated><content type="html" xml:lang="en-GB"><![CDATA[<p>A quick and simple post to kick off the new year looking at another cool iOS 5 UIKit addition. The UIStepper class provides a simple means to increment and decrement a value. You can get the idea from the screenshot below which illustrates how the control works:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.squarespace.com/storage/post-images/2012/2012-01-04-001.png?__SQUARESPACE_CACHEVERSION=1325711392080" alt="" /></span></span></p>
<p>The UIStepper is a bit like a UISwitch or UISegmentedControl in appearance except that it consists of +/- symbols that increment/decrement an internal value. If you hook the value changed event to a target method you can then retrieve the value and use it to update another user interface element such as a UILabel to display the current value:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">IBAction</span>)stepperChanged:(<span style="color: #7332a8;">UIStepper</span> *)sender {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">  NSUInteger</span> value = sender.<span style="color: #7332a8;">value</span>;</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">  self</span>.<span style="color: #538187;">counter</span>.<span style="color: #7332a8;">text</span> = [<span style="color: #7332a8;">NSString</span> <span style="color: #410d80;">stringWithFormat</span>:<span style="color: #cc2324;">@"%03d"</span>,value];</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p>&nbsp;</p>
<p>By default, the UIStepper has a minimumValue of 0 and a maximumValue of 100 (both properties are of type double) and a stepValue of 1 which means the value increments/decrements by 1 each time the +/- symbols are touched. By default the increment/decrement action is also set to autorepeat which means that the value auto decrements/increments as long as the control is pressed. This being Apple there is the usual attention to detail so the stepper smoothly accelerates the longer you press the control.</p>
<p>Another useful property allows you to control whether the value wraps when it reaches the minimum or maximum values. By default the wraps property is set to NO. The final property, continuous, controls whether the value changes are sent immediately or only when the user touch action ends. By default this property is set to YES so you get each value change immediately.</p>
<p>You can of course change all of these defaults by setting the appropriate property on the UIStepper object:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">self</span>.<span style="color: #538187;">stepper</span>.<span style="color: #7332a8;">wraps</span> = <span style="color: #b80ca1;">YES</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">self</span>.<span style="color: #538187;">stepper</span>.<span style="color: #7332a8;">autorepeat</span> = <span style="color: #b80ca1;">YES</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">self</span>.<span style="color: #538187;">stepper</span>.<span style="color: #7332a8;">continuous</span> = <span style="color: #b80ca1;">YES</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;"> </span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span><span style="color: #538187;">stepper</span><span style="color: #000000;">.</span>minimumValue<span style="color: #000000;"> = </span><span style="color: #3d00d6;">0</span><span style="color: #000000;">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;"> </span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span><span style="color: #538187;">stepper</span><span style="color: #000000;">.</span>maximumValue<span style="color: #000000;"> = </span><span style="color: #3d00d6;">100</span><span style="color: #000000;">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">self</span>.<span style="color: #538187;">stepper</span>.<span style="color: #7332a8;">stepValue</span> = <span style="color: #3d00d6;">1</span>;</p>
<p>&nbsp;</p>
<p>There is very little code to share but if you want to play with the UIStepper control you can find the example code in my <a href="https://github.com/kharrison/CodeExamples">Github Code Examples</a> repository.</p>
]]></content></entry><entry><title>UIAlertView changes in iOS 5</title><category term="UIAlertView"/><category term="UIKit"/><category term="ios"/><category term="ios5"/><id>http://useyourloaf.com/blog/2011/12/14/uialertview-changes-in-ios-5.html</id><link rel="alternate" type="text/html" href="http://useyourloaf.com/blog/2011/12/14/uialertview-changes-in-ios-5.html"/><author><name>Keith</name></author><published>2011-12-14T21:27:17Z</published><updated>2011-12-14T21:27:17Z</updated><content type="html" xml:lang="en-GB"><![CDATA[<p><em>The UIAlertView class has been available since iOS 2. It is similar to the UIActionSheet class but generally the UIAlertView is used to display an alert message to the user whereas UIActionSheet is useful when you want the user to confirm or choose between a set of options.&nbsp;This post will look at some useful additions to UIAlertView in iOS 5 however that also permit the user to enter some text into the alert view.</em></p>
<h3>The Default Style</h3>
<p>Before we look at what has changed in iOS 5 it is probably worth a quick recap of how UIAlertView worked in iOS 4. In all of these examples I will use an alert view with two buttons, a cancel button and an OK button. The code to create and show a basic UIAlertView is as follows:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">UIAlertView</span> *alertView = [[<span style="color: #7332a8;">UIAlertView</span> <span style="color: #410d80;">alloc</span>] <span style="color: #410d80;">initWithTitle</span>:<span style="color: #cc2324;">@&#8221;DefaultStyle&#8221;</span></p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">                                                    message</span>:<span style="color: #cc2324;">@"the default alert view style"</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">                                                   delegate</span>:<span style="color: #b80ca1;">self</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">                                          cancelButtonTitle</span>:<span style="color: #cc2324;">@"Cancel"</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">                                          otherButtonTitles</span>:<span style="color: #cc2324;">@"OK"</span>, <span style="color: #b80ca1;">nil</span>];</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[alertView <span style="color: #410d80;">show</span>];</p>
<p>&nbsp;</p>
<p>The initialiser is fairly self-explanatory, it takes a title and a longer description text message which is displayed in the body of the alert view. The delegate is optional and for simple alerts can be set to nil. As I will show in a moment the delegate is required if you want to interact with the alert view for example to find out which button the user pressed.</p>
<p>The cancelButtonTitle may be nil if you do not want a cancel button otherwise it is set to the text to display in the cancel button. Finally there is a nil-terminated list of titles for additional buttons to show in the alert. In this case we just add an OK button.&nbsp;The appearance of the alert view is shown below:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-12-14-001.png?__SQUARESPACE_CACHEVERSION=1323898657315" alt="" /></span></span></p>
<p>The view is dismissed by pressing either the Cancel or OK buttons. If you want to know which button the user pressed you need to implement some methods from the UIAlertViewDelegate. First we make our view controller adopt the delegate protocol:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #b80ca1;">@interface</span><span style="color: #000000;"> UYLViewController : </span>UIViewController<span style="color: #000000;"> &lt;</span>UIAlertViewDelegate<span style="color: #000000;">&gt;</span></p>
<p>&nbsp;</p>
<p>Then in the view controller we implement alertView:didDismissWithButtonIndex as follows:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">void</span>)alertView:(<span style="color: #7332a8;">UIAlertView</span> *)alertView didDismissWithButtonIndex:(<span style="color: #7332a8;">NSInteger</span>)buttonIndex</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #cc2324;"><span style="color: #000000;">  </span><span style="color: #410d80;">NSLog</span><span style="color: #000000;">(</span>@"Alert View dismissed with button at index %d"<span style="color: #000000;">,buttonIndex);</span></pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p>&nbsp;</p>
<p>The buttonIndex tells us which button was pressed to dismiss the view. The index starts at 0 so in our example with two buttons the Cancel button will give a value of 0 and the OK button will give 1. Of course you will probably want to do something more useful than log the result in a real application.</p>
<h3>Plain Text Input</h3>
<p>With iOS 5 the UIKit framework has added UIAlertView styles that allow for user input directly into the alert view. This is useful when you need to get a small amount of text input from the user such as a username or password before performing a task. The most simple style is to allow plain text input. The code to create and show a plain text input style alert view is as follows:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">UIAlertView</span> *alertView = [[<span style="color: #7332a8;">UIAlertView</span> <span style="color: #410d80;">alloc</span>] <span style="color: #410d80;">initWithTitle</span>:<span style="color: #cc2324;">@&#8221;PlainTextStyle&#8221;</span></p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">                                                    message</span>:<span style="color: #cc2324;">@"Enter plain text"</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">                                                   delegate</span>:<span style="color: #b80ca1;">self</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">                                          cancelButtonTitle</span>:<span style="color: #cc2324;">@"Cancel"</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">                                          otherButtonTitles</span>:<span style="color: #cc2324;">@"OK"</span>, <span style="color: #b80ca1;">nil</span>];</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;"> alertView.</span><span style="color: #7332a8;">alertViewStyle</span><span style="color: #000000;"> = </span>UIAlertViewStylePlainTextInput<span style="color: #000000;">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">[alertView <span style="color: #410d80;">show</span>];</p>
<p>&nbsp;</p>
<p>This is similar to creating the default alert view with the exception that we are setting the alertViewStyle property. This property is new in iOS 5 and takes a UIAlertViewStyle to set the style of the alert view. In this case we use UIAlertViewStylePlainTextInput which results in an alert view that looks like this:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-12-14-002.png?__SQUARESPACE_CACHEVERSION=1323898675492" alt="" /></span></span></p>
<p>The display and dismissal of the keyboard is handled for you to allow the user to enter text into the text field. You can access the text that the user has entered from the delegate we previously used to determine which button was pressed:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">UITextField</span> *textField = [alertView <span style="color: #410d80;">textFieldAtIndex</span>:<span style="color: #3d00d6;">0</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">NSLog</span>(<span style="color: #cc2324;">@&#8221;Plain text input: %@&#8221;</span>,textField.<span style="color: #7332a8;">text</span>);</p>
<p>&nbsp;</p>
<p>Note that the text field is accessed via an instance method, textFieldAtIndex, which as the name suggests takes the index of the text field we want. The UIAlertViewStylePlainTextInput alert style contains a single text field at index 0.</p>
<h3>Secure Text Input</h3>
<p>The plain text input style is obviously not great if the input you want from the user is a password. Typically when entering a password iOS masks characters as they are typed. To get that style of user input we can use the UIAlertViewStyleSecureTextInput:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;"> alertView.</span><span style="color: #7332a8;">alertViewStyle</span><span style="color: #000000;"> = </span>UIAlertViewStyleSecureTextInput<span style="color: #000000;">;</span></p>
<p>&nbsp;</p>
<p>The resulting UIAlertView looks the same as the plain text version with the exception that characters are masked a few seconds after they are entered:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-12-14-003.png?__SQUARESPACE_CACHEVERSION=1323898700635" alt="" /></span></span></p>
<h3>Login and Password Input</h3>
<p>The final style covers the situation where you want to get both a username and a password in a single alert view. The UIAlertViewStyleLoginAndPasswordInput style gives us an alert view that looks as follows:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-12-14-004.png?__SQUARESPACE_CACHEVERSION=1323898720659" alt="" /></span></span></p>
<p>The login name field is a plain text field and the password field is a secure text field. In this case we have two text fields that we need to retrieve in the delegate method:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">UITextField</span> *loginField = [alertView <span style="color: #410d80;">textFieldAtIndex</span>:<span style="color: #3d00d6;">0</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">NSLog</span>(<span style="color: #cc2324;">@&#8221;Login input: %@&#8221;</span>,loginField.<span style="color: #7332a8;">text</span>);</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">UITextField</span> *passwordField = [alertView <span style="color: #410d80;">textFieldAtIndex</span>:<span style="color: #3d00d6;">1</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">NSLog</span>(<span style="color: #cc2324;">@&#8221;Password input: %@&#8221;</span>,passwordField.<span style="color: #7332a8;">text</span>);</p>
<h3>Dynamically enabling/disabling the OK button</h3>
<p>One minor refinement we can make when expecting input from the user is to only enable the OK button when the user has actually entered some text. To perform this validation we need to implement an extra delegate method:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">BOOL</span>)alertViewShouldEnableFirstOtherButton:(<span style="color: #7332a8;">UIAlertView</span> *)alertView</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;"><span style="color: #7332a8;">  UITextField</span> *textField = [alertView <span style="color: #410d80;">textFieldAtIndex</span>:<span style="color: #3d00d6;">0</span>];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">  if</span> ([textField.<span style="color: #7332a8;">text</span> <span style="color: #410d80;">length</span>] == <span style="color: #3d00d6;">0</span>)</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">    return</span> <span style="color: #b80ca1;">NO</span>;</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  }</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;"><span style="color: #000000;">  </span>return<span style="color: #000000;"> </span>YES<span style="color: #000000;">;</span></pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p>&nbsp;</p>
<p>The alertViewShouldEnableFirstOtherButton delegate method is called each time the user modifies a text input field in the alert view. It return a BOOL which indicates if the first other button (the OK button in our example) should be enabled or not.</p>
<p>Of course you could do some more sophisticated validation if required but in this case we just check if the user has entered some text into the first text input field. If the text field is empty we return NO which disables the OK button. As soon as the user enters at least one character it is enabled. The Cancel button remains enabled at all times.</p>
<h3>Wrapping Up</h3>
<p>With iOS 5 the UIAlertView class provides a quick and easy way to get a username or password from the user. There is not much code required to implement these additional alert view styles but if you want to play around with the example app I used to generate the screenshots for this post you can find it <a href="http://useyourloaf.com/storage/code/examples/AlertView.zip">here</a> or on my github <a href="https://github.com/kharrison/CodeExamples/tree/master/AlertView">Code Examples</a> page.</p>
]]></content></entry><entry><title>Creating Gesture Recognizers with Interface Builder</title><category term="Interface Builder"/><category term="ios"/><category term="splitviewcontroller"/><id>http://useyourloaf.com/blog/2011/11/24/creating-gesture-recognizers-with-interface-builder.html</id><link rel="alternate" type="text/html" href="http://useyourloaf.com/blog/2011/11/24/creating-gesture-recognizers-with-interface-builder.html"/><author><name>Keith</name></author><published>2011-11-24T21:47:38Z</published><updated>2011-11-24T21:47:38Z</updated><content type="html" xml:lang="en-GB"><![CDATA[<p><em>Whilst I was playing around with Split View Controllers in my <a href="http://useyourloaf.com/blog/2011/11/16/mail-app-style-split-view-controller-with-a-sliding-master-v.html">last post</a> I missed one small trick to eliminate some code. I also overlooked a bug that I need to correct.</em></p>
<p>The example made use of gesture recognizers to allow the master view to be swiped on and off screen. However I created and configured these objects in code rather than with Interface Builder. In this post I will show how easy it is to create gesture recognizers with IB and eliminate some code.</p>
<p><span style="font-size: 16px; font-weight: bold;">A quick recap</span></p>
<p>Just by way of a recap the example app I used in the last post made use of three gesture recognizers. These were created in the viewDidLoad method of the DetailViewController and added to the detail view. The code that was used to create the three objects is shown below:</p>
<pre style="font: normal normal normal 11px/normal Menlo; color: #7332a8; margin: 0px;"><span style="color: #000000;">   </span>UISwipeGestureRecognizer<span style="color: #000000;"> *swipeLeft = [[</span>UISwipeGestureRecognizer<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; color: #7332a8; margin: 0px;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                          initWithTarget</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; color: #7332a8; margin: 0px;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                                  action</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">@selector</span><span style="color: #000000;">(handleSwipeLeft)];</span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; color: #410d80; margin: 0px;"><span style="color: #000000;">   swipeLeft.</span><span style="color: #7332a8;">direction</span><span style="color: #000000;"> = </span>UISwipeGestureRecognizerDirectionLeft<span style="color: #000000;">;</span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; color: #410d80; margin: 0px;"><span style="color: #000000;">   [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span><span style="color: #7332a8;">view</span><span style="color: #000000;"> </span>addGestureRecognizer<span style="color: #000000;">:swipeLeft];</span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; margin: 0px;">   [swipeLeft <span style="color: #410d80;">release</span>];</pre>
<p style="font: normal normal normal 11px/normal Menlo; min-height: 13px; margin: 0px;">&nbsp;</p>
<pre style="font: normal normal normal 11px/normal Menlo; color: #7332a8; margin: 0px;"><span style="color: #000000;">   </span>UISwipeGestureRecognizer<span style="color: #000000;"> *swipeRight = [[</span>UISwipeGestureRecognizer<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; color: #7332a8; margin: 0px;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                           initWithTarget</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; color: #7332a8; margin: 0px;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                                   action</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">@selector</span><span style="color: #000000;">(handleSwipeRight)];</span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; color: #410d80; margin: 0px;"><span style="color: #000000;">   swipeRight.</span><span style="color: #7332a8;">direction</span><span style="color: #000000;"> = </span>UISwipeGestureRecognizerDirectionRight<span style="color: #000000;">;</span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; margin: 0px;">   [<span style="color: #b80ca1;">self</span>.<span style="color: #7332a8;">view</span> <span style="color: #410d80;">addGestureRecognizer</span>:swipeRight];</pre>
<pre style="font: normal normal normal 11px/normal Menlo; margin: 0px;">   [swipeRight <span style="color: #410d80;">release</span>];</pre>
<p style="font: normal normal normal 11px/normal Menlo; min-height: 13px; margin: 0px;">&nbsp;</p>
<pre style="font: normal normal normal 11px/normal Menlo; color: #7332a8; margin: 0px;"><span style="color: #000000;">   </span>UITapGestureRecognizer<span style="color: #000000;"> *tap = [[</span>UITapGestureRecognizer<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; color: #7332a8; margin: 0px;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                  initWithTarget</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; color: #7332a8; margin: 0px;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                          action</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">@selector</span><span style="color: #000000;">(handleTap)];</span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; color: #410d80; margin: 0px;"><span style="color: #000000;">   [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span><span style="color: #7332a8;">view</span><span style="color: #000000;"> </span>addGestureRecognizer<span style="color: #000000;">:tap];</span></pre>
<pre style="font: normal normal normal 11px/normal Menlo; margin: 0px;">   [tap <span style="color: #410d80;">release</span>];</pre>
<p>&nbsp;</p>
<p>Each gesture recognizer is allocated and initialised with its appropriate target and action, there is some gesture specific configuration such as setting the direction of the swipe or the number of taps we expect and then finally the gesture is added to the view.</p>
<h3>Gesture Recognizers in Interface Builder</h3>
<p>Interface Builder contains a full set of gesture recognizers in its objects library. So instead of creating these objects manually with code we can just drag the required gestures onto our view in the UYLDetailViewController XIB.</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-24a-001.png?__SQUARESPACE_CACHEVERSION=1322262952682" alt="" /></span></span></p>
<p>Before I do that though I need to correct an error in the example I showed last time. The gesture recognizers were assigned to the top level UIView which includes the toolbar and the toolbar button. This meant that any attempt to tap on the toolbar button was intercepted by the gesture recognizer preventing the button action from being called.</p>
<p>To correct this error I have introduced a subview that covers the entire user interface with the exception of the toolbar. The gesture recognizers can then be assigned to this subview leaving taps on the toolbar button to be handled by the button.&nbsp;For this example we need one Tap Gesture Recognizer object and two Swipe Gesture Recognizer objects. Dragging these objects onto the subview leaves us with a XIB file looks as follows:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-24a-002.png?__SQUARESPACE_CACHEVERSION=1322263012963" alt="" /></span></span></p>
<p>It is the second view in this list that the gestures are assigned to. If you find your gestures are not working check the Referencing Outlet Collections connection in Interface Builder to ensure they are connected to the correct view:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-24a-003.png?__SQUARESPACE_CACHEVERSION=1322263092245" alt="" /></span></span></p>
<p>With the gestures added, configuration becomes easier as the inspector shows you the gesture specific configuration options. So the tap gesture allows you set to the number of taps and touches you want to recognize:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-24a-004.png?__SQUARESPACE_CACHEVERSION=1322263118210" alt="" /></span></span></p>
<p>The swipe gesture allows you set the direction of the swipe (left, right, up, down) and the number of touches:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-24a-005.png?__SQUARESPACE_CACHEVERSION=1322263138220" alt="" /></span></span></p>
<p>The final step is to set the target-action for each gesture. Using IB you can create the target-action by control-clicking on the object and then dragging into the implementation file. IB will then prompt you for the name of the action to insert:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-24a-006.png?__SQUARESPACE_CACHEVERSION=1322263159226" alt="" /></span></span></p>
<p>Since in this case we already have the action methods defined we will take a slightly different approach. We will first fix the methods to add IBAction hints for Xcode and then using the same control-click method drag each recognizer object to its method. As you mouse over the action it highlights to show the connection:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-24a-007.png?__SQUARESPACE_CACHEVERSION=1322263189802" alt="" /></span></span></p>
<p>With the gestures configured and connected there is nothing more to do other than clean up the now redundant code from the view controller. A quick compile and run should confirm that the gestures are recognised and function as before.</p>
<p>The updated Xcode project can be found <a href="http://useyourloaf.com/storage/code/examples/MasterSlide.zip">here</a> or in my <a href="https://github.com/kharrison/CodeExamples/tree/master/MasterSlide">CodeExamples</a> github repository.</p>
]]></content></entry><entry><title>Mail app style Split View Controller with a sliding master view</title><category term="iPhone"/><category term="splitviewcontroller"/><id>http://useyourloaf.com/blog/2011/11/16/mail-app-style-split-view-controller-with-a-sliding-master-v.html</id><link rel="alternate" type="text/html" href="http://useyourloaf.com/blog/2011/11/16/mail-app-style-split-view-controller-with-a-sliding-master-v.html"/><author><name>Keith</name></author><published>2011-11-16T21:51:17Z</published><updated>2011-11-16T21:51:17Z</updated><content type="html" xml:lang="en-GB"><![CDATA[<p><em>In a <a href="http://useyourloaf.com/blog/2011/10/19/ios-5-split-view-controller.html">recent post</a> I covered a change introduced with iOS 5 that allows the master view of a split view controller to always remain visible in portrait mode. A couple of readers asked if there were any changes to allow the master view to be displayed/hidden with a swipe gesture similar to the way the mail app from Apple now works. My quick answer was that whilst there are no changes in iOS 5 to directly support that style of transition all the functionality to implement it already exists. I thought I would try to expand on that answer with a full example in this post.</em></p>
<h3>Sliding Master View</h3>
<p>To illustrate the idea I will use a very simple master and detail view. The master view is a UITableView with each row named after the row index. The detail view is then simply a label showing the currently selected item. The title of the detail view also shows the selected item. The UI in landscape orientation is shown below:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-14-001.png?__SQUARESPACE_CACHEVERSION=1321480427404" alt="" /></span></span></p>
<p>In portrait mode there is a button in the toolbar that can be used to show the master view as illustrated below. This looks similar to the standard layout of a split view controller when used with a popover.</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-14-002.png?__SQUARESPACE_CACHEVERSION=1321480491873" alt="" /></span></span></p>
<p>The difference happens when the master view is displayed either by touching the toolbar button or by using a swipe right gesture. Instead of showing the master view in a popover it slides into view from the left margin covering a portion of the detail view (and the toolbar button). The master view can be dismissed by touching or swiping left in the detailed view.</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-14-003.png?__SQUARESPACE_CACHEVERSION=1321480516483" alt="" /></span></span></p>
<p>Compare this with the way a master view is displayed with a popover in the standard split view controller:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-18-002.png?__SQUARESPACE_CACHEVERSION=1321480601827" alt="" /></span></span></p>
<h3>Xcode Master-Detail Template</h3>
<p>I was going to base this example on the Xcode Master-Detail template but to be honest there is not much left from the template so if you want to follow along you may as well just start with an empty application. Whilst on the topic of Xcode templates it is interesting to note that the Master-Detail template does not follow the Apple iOS Human Interface Guidelines. In particular it is recommended not to use navigation controllers for both the master and detail views:</p>
<blockquote>
<p><strong style="font-family: 'Lucida Grande', Geneva, Helvetica, Arial, sans-serif; font-size: 13px; font-weight: bold;">Avoid displaying a navigation bar in both panes at the same time</strong>. Doing this would make it very difficult for users to discern the relationship between the two panes.</p>
</blockquote>
<p>In fact if you create the Split View Controller with Interface Builder it will not even allow you to place a navigation controller as the detail view controller. This is odd as the Apple settings apps actually appears to use a navigation controller for the detail controller, though not for the master view controller. Of course, if you really want to have navigation controllers in both panes you can create the split view controller in code which is what the Master-Detail template does:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #000000;"> </span>UYLMasterViewController<span style="color: #000000;"> *masterViewController = [[[</span>UYLMasterViewController<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span><span style="color: #410d80;">initWithNibName</span><span style="color: #000000;">:</span><span style="color: #cc2324;">@&rdquo;UYLMasterViewController&rdquo;</span><span style="color: #000000;"> </span><span style="color: #410d80;">bundle</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">nil</span><span style="color: #000000;">] </span><span style="color: #410d80;">autorelease</span><span style="color: #000000;">];</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">UINavigationController</span> *masterNavigationController = [[[<span style="color: #7332a8;">UINavigationController</span> <span style="color: #410d80;">alloc</span>] <span style="color: #410d80;">initWithRootViewController</span>:masterViewController] <span style="color: #410d80;">autorelease</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #000000;"> </span>UYLDetailViewController<span style="color: #000000;"> *detailViewController = [[[</span>UYLDetailViewController<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span><span style="color: #410d80;">initWithNibName</span><span style="color: #000000;">:</span><span style="color: #cc2324;">@&rdquo;UYLDetailViewController&rdquo;</span><span style="color: #000000;"> </span><span style="color: #410d80;">bundle</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">nil</span><span style="color: #000000;">] </span><span style="color: #410d80;">autorelease</span><span style="color: #000000;">];</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">UINavigationController</span> *detailNavigationController = [[[<span style="color: #7332a8;">UINavigationController</span> <span style="color: #410d80;">alloc</span>] <span style="color: #410d80;">initWithRootViewController</span>:detailViewController] <span style="color: #410d80;">autorelease</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;"> </span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span><span style="color: #538187;">splitViewController</span><span style="color: #000000;"> = [[[</span>UISplitViewController<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span><span style="color: #410d80;">init</span><span style="color: #000000;">] </span><span style="color: #410d80;">autorelease</span><span style="color: #000000;">];</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">self</span>.<span style="color: #538187;">splitViewController</span>.<span style="color: #7332a8;">delegate</span> = detailViewController;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">self</span>.<span style="color: #538187;">splitViewController</span>.<span style="color: #7332a8;">viewControllers</span> = [<span style="color: #7332a8;">NSArray</span> <span style="color: #410d80;">arrayWithObjects</span>:masterNavigationController, detailNavigationController, <span style="color: #b80ca1;">nil</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #000000;"> </span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span>window<span style="color: #000000;">.</span><span style="color: #7332a8;">rootViewController</span><span style="color: #000000;"> = </span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span>splitViewController<span style="color: #000000;">;</span></p>
<p>&nbsp;</p>
<p>If you are going to use this template you should note that it omits to give the master view controller a reference to the detail view controller (see later) which means you can waste a lot of time wondering why your detail view is not getting updated&hellip;</p>
<h3>Getting Started</h3>
<p>So starting with a fresh Xcode iPad project the first thing I did was create the NIB file for the main window which contains the Split View Controller. The Object layout in Interface Builder is shown below:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-14-005.png?__SQUARESPACE_CACHEVERSION=1321480653475" alt="" /></span></span></p>
<p>The Window and Split View Connector objects are connected to outlets in the Application Delegate:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #b80ca1;">@interface</span><span style="color: #000000;"> UYLAppDelegate : </span>UIResponder<span style="color: #000000;"> &lt;</span>UIApplicationDelegate<span style="color: #000000;">&gt;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;">@property<span style="color: #000000;"> (</span>retain<span style="color: #000000;">, </span>nonatomic<span style="color: #000000;">) </span>IBOutlet<span style="color: #000000;"> </span><span style="color: #7332a8;">UIWindow</span><span style="color: #000000;"> *window;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;">@property<span style="color: #000000;"> (</span>retain<span style="color: #000000;">, </span>nonatomic<span style="color: #000000;">) </span>IBOutlet<span style="color: #000000;"> </span><span style="color: #7332a8;">UISplitViewController</span><span style="color: #000000;"> *splitViewController;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;">@end</p>
<p>&nbsp;</p>
<p>The Split View Controller always contains two view controllers. The first is the master view controller which will appear in the left-hand pane and the second is the detailed view controller which will appear in the right-hand pane. In this example the master view controller is a navigation controller which contains our class UYLMasterViewController as its root view controller. The detailed view controlled is named UYLDetailViewController.</p>
<p>Normally when implementing the UISplitViewControllerDelegate protocol you would set the delegate of the split view controller to be the detail view controller. If you refer back to the code from the Xcode Master-Detail template you will see that it does exactly that. However the delegate protocol is only needed if you want to implement the popover controller approach or otherwise manage changes to the visibility of the master view controller. In this example we will not be implementing a popover controller so we do not need to set the delegate.</p>
<p>I will not show the NIB files for the master and detail views as they are trivial but for reference here is the interface definition for UYLMasterViewController:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #b80ca1;">@class</span><span style="color: #000000;"> </span>UYLDetailViewController<span style="color: #000000;">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">@interface</span> UYLMasterViewController : <span style="color: #7332a8;">UITableViewController</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;">@property<span style="color: #000000;"> (</span>retain<span style="color: #000000;">, </span>nonatomic<span style="color: #000000;">) </span>IBOutlet<span style="color: #000000;"> </span><span style="color: #538187;">UYLDetailViewController</span><span style="color: #000000;"> *detailViewController;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;">@end</p>
<p>&nbsp;</p>
<p>Note that we have defined a property (and IB outlet) for the detailViewController. We will use this later to allow the master view controller to update the detail view controller when the user selects a row. The connection between the master view controller outlet and the detail view controller object is made in the Main Window interface build NIB file.</p>
<p>The definition of the UYLDetailViewController is as follows:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #b80ca1;">@class</span><span style="color: #000000;"> </span>UYLMasterViewController<span style="color: #000000;">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">@interface</span> UYLDetailViewController : <span style="color: #7332a8;">UIViewController</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;">@property<span style="color: #000000;"> (</span>retain<span style="color: #000000;">, </span>nonatomic<span style="color: #000000;">) </span><span style="color: #7332a8;">NSNumber</span><span style="color: #000000;"> *detailItem;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;">@property<span style="color: #000000;"> (</span>retain<span style="color: #000000;">, </span>nonatomic<span style="color: #000000;">) </span>IBOutlet<span style="color: #000000;"> </span><span style="color: #7332a8;">UIToolbar</span><span style="color: #000000;"> *toolbar;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;">@property<span style="color: #000000;"> (</span>retain<span style="color: #000000;">, </span>nonatomic<span style="color: #000000;">) </span>IBOutlet<span style="color: #000000;"> </span><span style="color: #7332a8;">UILabel</span><span style="color: #000000;"> *detailTitle;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">@property</span> (<span style="color: #b80ca1;">retain</span>, <span style="color: #b80ca1;">nonatomic</span>) <span style="color: #b80ca1;">IBOutlet</span> <span style="color: #7332a8;">UILabel</span> *detailDescriptionLabel;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;">@property<span style="color: #000000;"> (</span>assign<span style="color: #000000;">, </span>nonatomic<span style="color: #000000;">) </span>BOOL<span style="color: #000000;"> masterIsVisible;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #b80ca1;">@end</p>
<p>&nbsp;</p>
<p>This is a simple UIViewController containing a UIToolbar which we will use to hold a button and a couple of UILabel objects which will be updated based on the contents of the detailItem object. In this simple example the detailItem object is just an NSNumber which will be set directly from the master view controller. Finally we define a boolean flag which we will use to track when the master view controller view is visible.</p>
<h3>Implementing the Master View Controller</h3>
<p>Actually the master view controller is almost trivial in that it is pretty much a standard UITableViewController. The only difference is that when a row in the table is selected we need to inform the detail view controller so that it can update its view. For the purposes of this example I have hardcoded the table to have a single section containing 20 rows. The content of each row is then simply constructed from the row number:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSUInteger</span> row = [indexPath <span style="color: #410d80;">row</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">cell.<span style="color: #7332a8;">textLabel</span>.<span style="color: #7332a8;">text</span> = [<span style="color: #7332a8;">NSString</span> <span style="color: #410d80;">stringWithFormat</span>:<span style="color: #cc2324;">@&rdquo;Item %u&rdquo;</span>, row+<span style="color: #3d00d6;">1</span>];</p>
<p>&nbsp;</p>
<p>Since we have a reference to the detail view controller we can directly set the detailItem whenever the user selects a row:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">void</span>)tableView:(<span style="color: #7332a8;">UITableView</span> *)tableView didSelectRowAtIndexPath:(<span style="color: #7332a8;">NSIndexPath</span> *)indexPath</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">  NSUInteger</span> item = [indexPath <span style="color: #410d80;">row</span>] +<span style="color: #3d00d6;">1</span>;</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">  NSNumber</span> *detailItem = [<span style="color: #7332a8;">NSNumber</span> <span style="color: #410d80;">numberWithInteger</span>:item];</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #000000;">   </span><span style="color: #b80ca1;">if</span><span style="color: #000000;"> (</span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span>detailViewController<span style="color: #000000;">)</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">   {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #000000;">     </span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span>detailViewController<span style="color: #000000;">.</span>detailItem<span style="color: #000000;"> = detailItem;</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">   }</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<h3>Implementing the Detail View Controller</h3>
<p>Before we look at how to make the master view slide on and off the screen I will cover the basic mechanism used to update the view whenever the master view controller makes a change. This is achieved by providing our own custom setter for the detailItem property which looks as follows:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">void</span>)setDetailItem:(<span style="color: #7332a8;">NSNumber</span> *)newDetailItem</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">  if</span> (<span style="color: #538187;">_detailItem</span> != newDetailItem) {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">    [<span style="color: #538187;">_detailItem</span> <span style="color: #410d80;">release</span>];</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #538187;">    _detailItem</span> = [newDetailItem <span style="color: #410d80;">retain</span>];</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #35595d;"><span style="color: #000000;">    [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span>configureView<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  }</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #000000;">  </span><span style="color: #b80ca1;">if</span><span style="color: #000000;"> (</span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span>masterIsVisible<span style="color: #000000;">) {</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #35595d;"><span style="color: #000000;">    [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span>hideMasterView<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  }</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p>&nbsp;</p>
<p>The storing of a value in the instance variable _detailItem is what you would expect to see in a compiler synthesised setter for a retained property. However in the situation where the value has changed we call the configureView method to update the view. In addition we also hide the master view but I will come back to that later. The configureView method is trivial in this example:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">void</span>)configureView</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">  if</span> (<span style="color: #b80ca1;">self</span>.<span style="color: #538187;">detailItem</span>) {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #b80ca1;">    self</span>.<span style="color: #538187;">detailTitle</span>.<span style="color: #7332a8;">text</span> = [<span style="color: #7332a8;">NSString</span> <span style="color: #410d80;">stringWithFormat</span>:<span style="color: #cc2324;">@"Item %@"</span>, <span style="color: #b80ca1;">self</span>.<span style="color: #538187;">detailItem</span>];</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #000000;">    </span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span>detailDescriptionLabel<span style="color: #000000;">.</span><span style="color: #7332a8;">text</span><span style="color: #000000;"> = [</span><span style="color: #7332a8;">NSString</span><span style="color: #000000;"> </span><span style="color: #410d80;">stringWithFormat</span><span style="color: #000000;">:</span><span style="color: #cc2324;">@"You selected item %@"</span><span style="color: #000000;">, </span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #000000;">&nbsp;</span><span style="color: #b80ca1;">                                                 self</span><span style="color: #000000;">.</span>detailItem<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  }</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<h3>Adding Gestures</h3>
<p>As described earlier we want to use a swipe right gesture to bring the master view controller into view and either a tap or swipe left to dismiss it. Of course we also only want this behaviour when we are in portrait mode. Gesture recognisers were introduced with the iPad in iOS 3.2 so we will make use of them here. A gesture recogniser is assigned to a view and in this case that means assigning them to the detail view controller view. We can do that easily enough in the viewDidLoad method of UYLDetailViewController:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">void</span>)viewDidLoad</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;">  [</span><span style="color: #b80ca1;">super</span><span style="color: #000000;"> </span>viewDidLoad<span style="color: #000000;">];</span></pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #000000;">   </span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span>masterIsVisible<span style="color: #000000;"> = </span><span style="color: #b80ca1;">NO</span><span style="color: #000000;">;</span></pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">   </span>UISwipeGestureRecognizer<span style="color: #000000;"> *swipeLeft = [[</span>UISwipeGestureRecognizer<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                          initWithTarget</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                                  action</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">@selector</span><span style="color: #000000;">(handleSwipeLeft)];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;">   swipeLeft.</span><span style="color: #7332a8;">direction</span><span style="color: #000000;"> = </span>UISwipeGestureRecognizerDirectionLeft<span style="color: #000000;">;</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;">   [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span><span style="color: #7332a8;">view</span><span style="color: #000000;"> </span>addGestureRecognizer<span style="color: #000000;">:swipeLeft];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">   [swipeLeft <span style="color: #410d80;">release</span>];</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">   </span>UISwipeGestureRecognizer<span style="color: #000000;"> *swipeRight = [[</span>UISwipeGestureRecognizer<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                           initWithTarget</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                                   action</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">@selector</span><span style="color: #000000;">(handleSwipeRight)];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;">   swipeRight.</span><span style="color: #7332a8;">direction</span><span style="color: #000000;"> = </span>UISwipeGestureRecognizerDirectionRight<span style="color: #000000;">;</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">   [<span style="color: #b80ca1;">self</span>.<span style="color: #7332a8;">view</span> <span style="color: #410d80;">addGestureRecognizer</span>:swipeRight];</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">   [swipeRight <span style="color: #410d80;">release</span>];</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">   </span>UITapGestureRecognizer<span style="color: #000000;"> *tap = [[</span>UITapGestureRecognizer<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                  initWithTarget</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">&nbsp;</span><span style="color: #410d80;">                                          action</span><span style="color: #000000;">:</span><span style="color: #b80ca1;">@selector</span><span style="color: #000000;">(handleTap)];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;">   [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span><span style="color: #7332a8;">view</span><span style="color: #000000;"> </span>addGestureRecognizer<span style="color: #000000;">:tap];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">   [tap <span style="color: #410d80;">release</span>];</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #76482d;"><span style="color: #000000;">   </span><span style="color: #b80ca1;">if</span><span style="color: #000000;"> (</span>UIInterfaceOrientationIsPortrait<span style="color: #000000;">(</span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.interfaceOrientation))</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">   {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #35595d;"><span style="color: #000000;">     [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span>addMasterButton<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">   }</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #35595d;"><span style="color: #000000;">   [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span>configureView<span style="color: #000000;">];</span></pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">&nbsp;</p>
<p>That looks like a lot of code but it is mostly straightforward:</p>
<ul>
<li>to get started we initialised the boolean flag we are using to track if the master view is visible in portrait mode.</li>
<li>Three separate gesture recognisers are then added to the view. Each gesture recogniser has a separate handler set as the action. The first two gestures are for swiping left and right which is specified by the direction property. The final gesture is for a tap which we will use for dismissing the master view.</li>
<li>If when the view is loaded we are already in portrait mode then we need to add a button to the toolbar to allow the user to view the master view (assuming they do not use the swipe right gesture).</li>
<li>Finally we call the configureView method we saw earlier to setup the view.</li>
</ul>
<p>There are three methods (handleSwipeLeft, handleSwipeRight, handleTap) to handle the various gestures. Since they are very similar I will just show handleSwipeRight:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">void</span>)handleSwipeRight</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #76482d;"><span style="color: #000000;">  </span><span style="color: #b80ca1;">if</span><span style="color: #000000;"> (</span>UIInterfaceOrientationIsPortrait<span style="color: #000000;">(</span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.interfaceOrientation))</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #35595d;"><span style="color: #000000;">    [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span>showMasterView<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  }</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p>Since we only want our gestures to work when we are in portrait mode we first test the current device orientation. Then if we are in portrait mode we call the showMasterView method to actually bring the master view on screen. The other two methods are almost identical, the only difference is that they call hideMasterView to move the master view off screen.</p>
<h3>Sliding the Master View On and Off Screen</h3>
<p>The one thing that I was not sure about when starting to write this example was exactly how to manipulate the master view. Since the master view is managed internally by the split view controller it is not documented how it shows or hides it when the device changes orientation. A quick look at the view frame in portrait mode tells us the answer. We can move it on and offscreen by adding or subtracting the view width to the x-coordinate of the view frame origin:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7082fd;"><strong>(gdb) </strong></span><strong>p rootFrame</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">$2 = {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">origin = {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">x = -320,</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">y = 0</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">},</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">size = {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">width = 320,</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">height = 1004</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<blockquote>
<p>At this point I have to add a small word or warning in case you decide to implement this approach in a shipping application. It does not use any undocumented API&rsquo;s but it does rely on a specific behaviour of split view controllers that Apple could change in a future release of iOS. So whilst this works now and is very likely to continue to work in future releases there are no guarantees it will not at some point break.</p>
</blockquote>
<p>With that warning out of the way we can look at the method to bring the master view controller view onscreen:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">void</span>)showMasterView</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #000000;">  </span><span style="color: #b80ca1;">if</span><span style="color: #000000;"> (!</span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span>masterIsVisible<span style="color: #000000;">)</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #538187;"><span style="color: #000000;">    </span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span>masterIsVisible<span style="color: #000000;"> = </span><span style="color: #b80ca1;">YES</span><span style="color: #000000;">;</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">    </span>NSArray<span style="color: #000000;"> *controllers = </span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.</span>splitViewController<span style="color: #000000;">.</span>viewControllers<span style="color: #000000;">;</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">    UIViewController</span> *rootViewController = [controllers <span style="color: #410d80;">objectAtIndex</span>:<span style="color: #3d00d6;">0</span>];</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">    UIView</span> *rootView = rootViewController.<span style="color: #7332a8;">view</span>;</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">    CGRect</span> rootFrame = rootView.<span style="color: #7332a8;">frame</span>;</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">    rootFrame.<span style="color: #7332a8;">origin</span>.<span style="color: #7332a8;">x</span> += rootFrame.<span style="color: #7332a8;">size</span>.<span style="color: #7332a8;">width</span>;</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;">    [</span><span style="color: #7332a8;">UIView</span><span style="color: #000000;"> </span>beginAnimations<span style="color: #000000;">:</span><span style="color: #cc2324;">@"showView"</span><span style="color: #000000;"> </span>context<span style="color: #000000;">:</span><span style="color: #b80ca1;">NULL</span><span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">    rootView.<span style="color: #7332a8;">frame</span> = rootFrame;</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #410d80;"><span style="color: #000000;">    [</span><span style="color: #7332a8;">UIView</span><span style="color: #000000;"> </span>commitAnimations<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  }</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p>Some explanation to walk you through this method:</p>
<ul>
<li>the first thing we do is check our boolean flag &ldquo;masterIsVisible&rdquo; to see if the master view is already visible. If it is hidden we set the flag to YES and proceed with actually bringing the view onscreen.</li>
<li>To bring the view onscreen we need to retrieve the root view controller that owns the view we want to display. This is easy enough as all view controllers that are contained in a split view controller have a reference to the split view controller. The first object in the viewControllers array is the &ldquo;master&rdquo; view controller. Note though that this is not our UYLMasterViewController object but the UINavigationController that is inserted at the root of the view controller hierarchy.</li>
<li>Once we have the view from the root view controller we can retrieve its frame and manipulate the x-coordinate of the frame origin to shift it onscreen by adding the width of the view. To make the view slide onto screen we enclose the change to view frame in an animation block.</li>
</ul>
<p>The hideMasterView method is very similar with the exception that we subtract the width of the view from the x-coordinate.</p>
<h3>Adding and Removing the Toolbar Button</h3>
<p>With the view now sliding on and off screen we need to handle the adding (and removal) of a button to the toolbar. You can consider this button optional in that it duplicates the functionality of the swipe right gesture to bring the master view onscreen. However it is not always obvious to users what gestures your app supports so having an additional UI element can sometimes help. One way to think about gestures is to treat them like keyboard shortcuts. Power users will make use of them but not all users may even discover the gesture. If you are going to skip the button consider making the master view have a tab or other visual cue that is visible when the rest of the view is offscreen (the Flixster iPad app is a good example of this approach).</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">void</span>)addMasterButton</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;">  </span>UIBarButtonItem<span style="color: #000000;"> *barButtonItem = [[</span>UIBarButtonItem<span style="color: #000000;"> </span><span style="color: #410d80;">alloc</span><span style="color: #000000;">] </span><span style="color: #410d80;">initWithTitle</span><span style="color: #000000;">:</span><span style="color: #cc2324;">@"Master"</span><span style="color: #000000;"> </span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">                                            style</span>:<span style="color: #410d80;">UIBarButtonItemStyleBordered</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">                                           target</span>:<span style="color: #b80ca1;">self</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #410d80;">                                           action</span>:<span style="color: #b80ca1;">@selector</span>(showMasterView)];</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">  NSMutableArray</span> *items = [[<span style="color: #b80ca1;">self</span>.<span style="color: #538187;">toolbar</span> <span style="color: #410d80;">items</span>] <span style="color: #410d80;">mutableCopy</span>];</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  [items <span style="color: #410d80;">insertObject</span>:barButtonItem <span style="color: #410d80;">atIndex</span>:<span style="color: #3d00d6;">0</span>];</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  [<span style="color: #b80ca1;">self</span>.<span style="color: #538187;">toolbar</span> <span style="color: #410d80;">setItems</span>:items <span style="color: #410d80;">animated</span>:<span style="color: #b80ca1;">YES</span>];</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  [items <span style="color: #410d80;">release</span>];</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  [barButtonItem <span style="color: #410d80;">release</span>];</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p>To add a button to the toolbar we actually need to create a UIBarButtonItem and add that to the UIToolbar items array. The easiest way to do that is to make a copy of the existing items array and insert our new bar button item as the first element of the array. In this case we do not have any other buttons on the toolbar but if we did this approach will preserve those other buttons. Note that the target:action of the button item is set to call the showMasterView method we saw previously.&nbsp;I will skip showing the removeMasterButton method as it simply removes the first item from the toolbar items array.</p>
<p>Now if you refer back to the viewDidLoad method you will see that we already have code to show the button if the device is already in portrait mode when the detail view controller is loaded:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #76482d;"><span style="color: #000000;"> </span><span style="color: #b80ca1;">if</span><span style="color: #000000;"> (</span>UIInterfaceOrientationIsPortrait<span style="color: #000000;">(</span><span style="color: #b80ca1;">self</span><span style="color: #000000;">.interfaceOrientation))</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #35595d;"><span style="color: #000000;">  [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span>addMasterButton<span style="color: #000000;">];</span></pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p>This is great but what about when the device changes orientation after the view is loaded?</p>
<h3>Handling Orientation Changes</h3>
<p>To handle the situation where the device switches back and forth between portrait and landscape orientations we need to implement the willRotateToInterfaceOrientation:toInterfaceOrientation:duration method:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #b80ca1;">void</span>)willRotateToInterfaceOrientation:(<span style="color: #7332a8;">UIInterfaceOrientation</span>)toInterfaceOrientation</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">duration:(<span style="color: #7332a8;">NSTimeInterval</span>)duration</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #76482d;"><span style="color: #000000;">  </span><span style="color: #b80ca1;">if</span><span style="color: #000000;"> (</span>UIInterfaceOrientationIsLandscape<span style="color: #000000;">(toInterfaceOrientation))</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #35595d;"><span style="color: #000000;">    [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span>hideMasterView<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #35595d;"><span style="color: #000000;">    [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span>removeMasterButton<span style="color: #000000;">];</span></pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;">&nbsp;</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  } <span style="color: #b80ca1;">else</span> {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #35595d;"><span style="color: #000000;">    [</span><span style="color: #b80ca1;">self</span><span style="color: #000000;"> </span>addMasterButton<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  }</pre>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p>So if we are moving to landscape orientation we hide the master view and remove the button for the toolbar. Likewise when moving to portrait orientation we simply need to add the button to the toolbar.</p>
<h3>Adding a Border to the Master View</h3>
<p>One final finishing touch is that we need to add a border to the master view to enclose the UITableView. You can spend some time making a nice shadowed box but for now I will just add a border in the App Delegate:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">UIView</span> *rootView = [[<span style="color: #b80ca1;">self</span>.<span style="color: #538187;">splitViewController</span>.<span style="color: #7332a8;">viewControllers</span> <span style="color: #410d80;">objectAtIndex</span>:<span style="color: #3d00d6;">0</span>] <span style="color: #410d80;">view</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">rootView.<span style="color: #7332a8;">layer</span>.<span style="color: #7332a8;">borderWidth</span> = <span style="color: #3d00d6;">1.0f</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">rootView.<span style="color: #7332a8;">layer</span>.<span style="color: #7332a8;">cornerRadius</span> =<span style="color: #3d00d6;">5.0f</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">rootView.<span style="color: #7332a8;">layer</span>.<span style="color: #7332a8;">shadowOpacity</span> = <span style="color: #3d00d6;">0.8f</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">rootView.<span style="color: #7332a8;">layer</span>.<span style="color: #7332a8;">shadowOffset</span> = <span style="color: #410d80;">CGSizeMake</span>(-<span style="color: #3d00d6;">5</span>, <span style="color: #3d00d6;">0</span>);</p>
<h3>Wrapping Up</h3>
<p>Congratulations if you made it this point - that was a lot of explanation for something which in the end is pretty straightforward. I will leave you with one final comment about this approach. As I mentioned during the post I am relying on a very specific implementation detail of the split view controller which could change in a future iOS release. It is always interesting to play with different implementations but I leave it to you to decide if you are comfortable with this approach for production code. My feeling is that if you want to go beyond Apple&rsquo;s implementation of split view controller it might be better to build the complete container class and abandon split view controller completely.</p>
<p>As always you can download the full example app <a href="http://useyourloaf.com/storage/code/examples/MasterSlide.zip">here</a> or in my <a href="https://github.com/kharrison/CodeExamples">CodeExamples</a> github repository.</p>
]]></content></entry><entry><title>Stanford iOS development course updated for iOS 5</title><category term="iPhone"/><category term="training"/><id>http://useyourloaf.com/blog/2011/11/16/stanford-ios-development-course-updated-for-ios-5.html</id><link rel="alternate" type="text/html" href="http://useyourloaf.com/blog/2011/11/16/stanford-ios-development-course-updated-for-ios-5.html"/><author><name>Keith</name></author><published>2011-11-16T21:01:47Z</published><updated>2011-11-16T21:01:47Z</updated><content type="html" xml:lang="en-GB"><![CDATA[<p>This quarter&#8217;s lectures from the excellent <a href="http://www.stanford.edu/class/cs193p/cgi-bin/drupal/">Stanford iOS App Development course</a> have just been published to <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=473757255">iTunesU</a>. This years course is again presented by Paul Hegarty and promises to cover iOS 5 specific topics such as iCloud.</p>
<p>At the time of writing only the first 6 lectures are up, so you still have time to catch up if you want to follow along. I recommend this course to anyone looking to get started on iOS development but I think it is also worthwhile for more experienced developers as they often have excellent guest presenters.</p>
]]></content></entry><entry><title>Settings Radio Group Element</title><category term="iPhone"/><category term="settings"/><id>http://useyourloaf.com/blog/2011/11/1/settings-radio-group-element.html</id><link rel="alternate" type="text/html" href="http://useyourloaf.com/blog/2011/11/1/settings-radio-group-element.html"/><author><name>Keith</name></author><published>2011-11-01T22:09:53Z</published><updated>2011-11-01T22:09:53Z</updated><content type="html" xml:lang="en-GB"><![CDATA[<p>Whilst playing with the <a href="http://useyourloaf.com/blog/2011/10/24/sync-preference-data-with-icloud.html">iCloud key-value store</a> I came across a new element for the iOS settings application. The Radio Group element was introduced in iOS 5 and is similar in functionality to the Multi Value element. Most of the iOS documentation does not yet mention the Radio Group element with the exception of the Settings Application Schema Reference. Also Xcode 4.2 does not provide direct support when editing the settings property list which makes it a pain to add.</p>
<p>Both elements allow the user to choose one option from a list of possible options but the Radio Group element avoids the need to display the choices on a second page.&nbsp;To illustrate the difference I will add both Multi Value and Radio Group elements to the settings bundle I used to illustrate how to <a href="http://useyourloaf.com/blog/2010/5/18/adding-a-settings-bundle-to-an-iphone-app.html">add a settings bundle to an iPhone app</a>. Refer back to that earlier post for the basics on setting up user preferences.</p>
<h3>Multi Value Element</h3>
<p>The visual appearance of the Multi Value element is shown below for the Retry preference:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-01-001.png?__SQUARESPACE_CACHEVERSION=1320185484864" alt="" /></span></span></p>
<p>The preference is displayed as a singe line which when tapped takes the user to a second page where the available options can be selected:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-01-002.png?__SQUARESPACE_CACHEVERSION=1320185526632" alt="" /></span></span></p>
<p>The equivalent entry in the settings property list is as follows:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-01-003.png?__SQUARESPACE_CACHEVERSION=1320185554500" alt="" /></span></span></p>
<p>The required fields are as follows:</p>
<ul>
<li>Type: PSMultiValueSpecifier</li>
<li>Title: This is the string which is displayed in the settings table.</li>
<li>Key: A string identifier which is used to set and retrieve the preference.</li>
<li>DefaultValue: Default value for the setting.</li>
<li>Values: An array containing the values the user must choose from. You can use any type supported by the preference file. Each value much have a corresponding title in the Titles array.</li>
<li>Titles: An array of strings which is displayed on the second page corresponding to the values defined in the Values array.</li>
</ul>
<p>You can also add a ShortTitles array which provides a shorter string to show in the preference row. Notice in the previous screenshots how the first page show the current value as &#8220;Always&#8221; whereas the corresponding value on the second page has the longer title &#8220;Always Retry&#8221;.</p>
<h3>Radio Group Element</h3>
<p>The Radio Group element removes the need to have a second page and shows all of the options on the initial preferences page as shown below for the Sync preference:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-01-004.png?__SQUARESPACE_CACHEVERSION=1320185609572" alt="" /></span></span></p>
<p>The entry in the settings property list is as follows:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://useyourloaf.com/storage/post-images/2011/2011-11-01-005.png?__SQUARESPACE_CACHEVERSION=1320185638674" alt="" /></span></span></p>
<p>At the time I am writing this post I am using Xcode 4.2 which does not show the Radio Group as a valid option in an iPhone settings list. This has the side effect that the Item line incorrectly shows the values from the previous item in the settings list. However this does not impact the values written to the settings file (right-click on the file and use Open As &gt; Source Code to see the actual XML).</p>
<p>The fields are similar to the Multi Value element except that the title is now optional since it serves as the title of the table section. Also you can add a FooterText string to include some extra explanatory text below the table group.</p>
<h3>Setting and Accessing Values</h3>
<p>Both preference settings can be accessed in a similar way via the NSUserDefaults class:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #7332a8;"><span style="color: #000000;"> </span>NSUserDefaults<span style="color: #000000;"> *defaults = [</span>NSUserDefaults<span style="color: #000000;"> </span><span style="color: #410d80;">standardUserDefaults</span><span style="color: #000000;">];</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSInteger</span> syncType = [defaults <span style="color: #410d80;">integerForKey</span>:<span style="color: #cc2324;">@&#8221;syncType&#8221;</span>];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #7332a8;">NSInteger</span> retry = [defaults <span style="color: #410d80;">integerForKey</span>:<span style="color: #cc2324;">@&#8221;retryStrategy&#8221;</span>];</p>
<h3>Wrapping Up</h3>
<p>As long as you do not have a huge list of settings I think the Radio Group element is a nicer choice for selecting from a set of options. It avoids the extra page and the title and footnote help make the settings easier to understand. I guess I should file some bug reports on Xcode and the documentation to ask Apple to update them now that the dust is settling from all the recent launch activity.</p>
]]></content></entry></feed>
