<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cocoa Is My Girlfriend &#187; iPad</title>
	<atom:link href="http://www.cimgf.com/category/ipad/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cimgf.com</link>
	<description>Taglines are for Windows programmers</description>
	<lastBuildDate>Wed, 11 Jan 2012 15:00:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Subduing CATiledLayer</title>
		<link>http://www.cimgf.com/2011/03/01/subduing-catiledlayer/</link>
		<comments>http://www.cimgf.com/2011/03/01/subduing-catiledlayer/#comments</comments>
		<pubDate>Tue, 01 Mar 2011 06:01:15 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPod Touch]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=1321</guid>
		<description><![CDATA[Many technologies we use as Cocoa/Cocoa Touch developers stand untouched by the faint of heart because often we simply don&#8217;t understand them and employing them can seem a daunting task. One of those technologies is found in Core Animation and is referred to as the CATiledLayer. It seems like a magical sort of technology because [...]]]></description>
			<content:encoded><![CDATA[<p>Many technologies we use as Cocoa/Cocoa Touch developers stand untouched by the faint of heart because often we simply don&#8217;t understand them and employing them can seem a daunting task. One of those technologies is found in Core Animation and is referred to as the CATiledLayer. It seems like a magical sort of technology because so much of its implementation is a bit of a black box and this fact contributes to it being misunderstood. CATiledLayer simply provides a way to draw very large images without incurring a severe memory hit. This is important no matter where you&#8217;re deploying, but it especially matters on iOS devices as memory is precious and when the OS tells you to free up memory, you better be able to do so or your app will be brought down. This blog post is intended to demonstrate that CATiledLayer works as advertised and implementing it is not as hard as it may have once seemed.
<span id="more-1321"></span></p>

<p><a href="http://www.cimgf.com/files/BitmapSlice.zip">Download Demo Project</a></p>

<h2>The Trick Is In Listening To The View</h2>

<p>Let me cut to the chase here and clue you in on what you need to do. The easiest way to take advantage of the CATiledLayer is to create a UIView based subclass and override the +layerClass class method to return a [CATiledLayer class].</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">+</span> layerClass
<span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>CATiledLayer class<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Then, you just need to override drawRect: and draw what it tells you to draw. That&#8217;s it! Listen to the UIView. It&#8217;s telling you in drawRect: which rectangle it wants to draw. So while your user is scrolling a scroll view that contains your view, for example, drawRect: will be getting called continuously. You just need to calculate how that rectangle corresponds to the image you&#8217;re wanting to draw.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>drawRect<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGRect<span style="color: #002200;">&#41;</span>rect
<span style="color: #002200;">&#123;</span>
  <span style="color: #11740a; font-style: italic;">// You cant get the current context if you need it.</span>
   CGContextRef context <span style="color: #002200;">=</span> UIGraphicsGetCurrentContext<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
  <span style="color: #11740a; font-style: italic;">// Your drawing code here ...</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>I&#8217;ll show you a fuller implementation of drawRect: later. Feel free to skip there now or even download the demo project if you want to see the project in action. First I&#8217;m going to discuss how we get our tiles and truly take advantage of the memory use reduction we get from the CATiledLayer.</p>

<h2>The Downside Is Tiling the Image</h2>

<p>So, now that you&#8217;ve implemented a UIView derived subclass that overrides drawRect: performance is going to improve drastically, right? Well, unfortunately, not exactly. If you pull the entire image into memory with -imageNamed or even -imageWithContentsOfFile, you&#8217;re going to be up against the exact same memory problem you had before using a tiled layer. So what are the solutions? Well, if there were a way to map tiles to bytes on disk, that would be great, but unfortunately that is far more complicated and I’m not even sure it&#8217;s possible. In the end, we have to actually tile the image manually and store the images on disk to be loaded on demand.</p>

<p>So, the first question I asked when I realized this is can I do the tiling programmatically and write the files out to disk or do I need to slice them up in a photo editor manually? Just like everything in programming, there are tradeoffs between various solutions. If you have a different part of your workflow where it makes sense to tile the images before sending them to the device, I would choose that solution, however, that doesn&#8217;t seem terribly likely. In most cases you&#8217;re probably going to need to tile the images on device programmatically. If that&#8217;s true, then I suggest that you don&#8217;t just tile every image, but rather set a threshold size. If your images reach a certain dimension, only tile those since it will take some time and processing power to do so.</p>

<p>Of course, you&#8217;re going to want to do your tiling on a background thread as to not block your user interface, but here is some basic image tiling code that will write your image tiles to disk. You can place this in an NSOperation or use a block and run it on a background queue.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>saveTilesOfSize<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGSize<span style="color: #002200;">&#41;</span>size 
               forImage<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIImage<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image 
            toDirectory<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>directoryPath 
            usingPrefix<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>prefix
<span style="color: #002200;">&#123;</span>
  CGFloat cols <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>image size<span style="color: #002200;">&#93;</span>.width <span style="color: #002200;">/</span> size.width;
  CGFloat rows <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>image size<span style="color: #002200;">&#93;</span>.height <span style="color: #002200;">/</span> size.height;
&nbsp;
  <span style="color: #a61390;">int</span> fullColumns <span style="color: #002200;">=</span> floorf<span style="color: #002200;">&#40;</span>cols<span style="color: #002200;">&#41;</span>;
  <span style="color: #a61390;">int</span> fullRows <span style="color: #002200;">=</span> floorf<span style="color: #002200;">&#40;</span>rows<span style="color: #002200;">&#41;</span>;
&nbsp;
  CGFloat remainderWidth <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>image size<span style="color: #002200;">&#93;</span>.width <span style="color: #002200;">-</span> 
                          <span style="color: #002200;">&#40;</span>fullColumns <span style="color: #002200;">*</span> size.width<span style="color: #002200;">&#41;</span>;
  CGFloat remainderHeight <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>image size<span style="color: #002200;">&#93;</span>.height <span style="color: #002200;">-</span> 
                          <span style="color: #002200;">&#40;</span>fullRows <span style="color: #002200;">*</span> size.height<span style="color: #002200;">&#41;</span>;
&nbsp;
&nbsp;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>cols &gt; fullColumns<span style="color: #002200;">&#41;</span> fullColumns<span style="color: #002200;">++</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>rows &gt; fullRows<span style="color: #002200;">&#41;</span> fullRows<span style="color: #002200;">++</span>;
&nbsp;
  CGImageRef fullImage <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>image CGImage<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> y <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; y &lt; fullRows; <span style="color: #002200;">++</span>y<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> x <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; x &lt; fullColumns; <span style="color: #002200;">++</span>x<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
      CGSize tileSize <span style="color: #002200;">=</span> size;
      <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>x <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span> <span style="color: #002200;">==</span> fullColumns <span style="color: #002200;">&amp;&amp;</span> remainderWidth &gt; <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Last column</span>
        tileSize.width <span style="color: #002200;">=</span> remainderWidth;
      <span style="color: #002200;">&#125;</span>
      <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>y <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span> <span style="color: #002200;">==</span> fullRows <span style="color: #002200;">&amp;&amp;</span> remainderHeight &gt; <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Last row</span>
        tileSize.height <span style="color: #002200;">=</span> remainderHeight;
      <span style="color: #002200;">&#125;</span>
&nbsp;
      CGImageRef tileImage <span style="color: #002200;">=</span> CGImageCreateWithImageInRect<span style="color: #002200;">&#40;</span>fullImage, 
                                        <span style="color: #002200;">&#40;</span>CGRect<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span><span style="color: #002200;">&#123;</span>x<span style="color: #002200;">*</span>size.width, y<span style="color: #002200;">*</span>size.height<span style="color: #002200;">&#125;</span>, 
                                          tileSize<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
      <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>imageData <span style="color: #002200;">=</span> UIImagePNGRepresentation<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>UIImage imageWithCGImage<span style="color: #002200;">:</span>tileImage<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
      <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>path <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@/%@%d_%d.png&quot;</span>, 
                        directoryPath, prefix, x, y<span style="color: #002200;">&#93;</span>;
      <span style="color: #002200;">&#91;</span>imageData writeToFile<span style="color: #002200;">:</span>path atomically<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
  <span style="color: #002200;">&#125;</span>    
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Let me walk you through this a little bit. We pass in the size of the tiles we want to break our image into. We pass in the image itself, the directory we want to save it to, and finally a prefix that we will use as a unique identifier for the file names for the image in question. We need this so that we can retrieve them again later when we&#8217;re ready display them.</p>

<p>The first thing we do is calculate the number of tiles we&#8217;re going to have in columns and rows by dividing the total width by the tile width and the total height by the tile height. The result is a floating point number. We then get the number of columns and rows that are full sized tiles by using floorf(). We then calculate the width of the last column and the height of last row. Next we iterate through the entire grid of what will soon be tiled images, columns per row. Then we extract the image data at the rect in question and write its contents to disk using an NSData. The filename format we&#8217;re using takes into account the x and y positions in our grid of tiles such that an image would have its tiles named:</p>

<p><pre>
&lt;directory&gt;/&lt;prefix&gt;x_y.png
</pre></p>

<p>Where directory and prefix are the strings passed into the function. The .png extension here is really just for clarity. It is completely unnecessary.</p>

<h2>Implementing Draw Rect</h2>

<p>The first implementation of CATiledLayer expected that you would create a delegate for your layer and then override</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>drawLayer<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CALayer<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>theLayer 
            inContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGContextRef<span style="color: #002200;">&#41;</span>theContext</pre></div></div>


<p>This was error prone for several reasons. The trouble was you couldn&#8217;t use both UIKit and Core Graphics calls to draw in the layer which people would often do. They would soon start asking <a href="http://stackoverflow.com/questions/2295151/catiledlayer-drawing-crash">why their app was crashing</a> and would discover that the problem could be solved by only drawing using only Core Graphics.</p>

<p>Now, in iOS4, things have gotten much easier. You can simply override drawRect: in your UIView subclass and everything works correctly. To draw my layer correctly, I adapted the drawing code you find in the <a href="https://deimos.apple.com/WebObjects/Core.woa/BrowsePrivately/adc.apple.com.4092349126.04109539109.4144345585?i=1699219987">PhotoScroller sample code from the WWDC 2010 sessions</a> (Link opens iTunes). It looks like this:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>drawRect<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGRect<span style="color: #002200;">&#41;</span>rect <span style="color: #002200;">&#123;</span>
 	CGContextRef context <span style="color: #002200;">=</span> UIGraphicsGetCurrentContext<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
  CGSize tileSize <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>CGSize<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span><span style="color: #2400d9;">256</span>, <span style="color: #2400d9;">256</span><span style="color: #002200;">&#125;</span>;
&nbsp;
  <span style="color: #a61390;">int</span> firstCol <span style="color: #002200;">=</span> floorf<span style="color: #002200;">&#40;</span>CGRectGetMinX<span style="color: #002200;">&#40;</span>rect<span style="color: #002200;">&#41;</span> <span style="color: #002200;">/</span> tileSize.width<span style="color: #002200;">&#41;</span>;
  <span style="color: #a61390;">int</span> lastCol <span style="color: #002200;">=</span> floorf<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CGRectGetMaxX<span style="color: #002200;">&#40;</span>rect<span style="color: #002200;">&#41;</span><span style="color: #002200;">-</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">/</span> tileSize.width<span style="color: #002200;">&#41;</span>;
  <span style="color: #a61390;">int</span> firstRow <span style="color: #002200;">=</span> floorf<span style="color: #002200;">&#40;</span>CGRectGetMinY<span style="color: #002200;">&#40;</span>rect<span style="color: #002200;">&#41;</span> <span style="color: #002200;">/</span> tileSize.height<span style="color: #002200;">&#41;</span>;
  <span style="color: #a61390;">int</span> lastRow <span style="color: #002200;">=</span> floorf<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CGRectGetMaxY<span style="color: #002200;">&#40;</span>rect<span style="color: #002200;">&#41;</span><span style="color: #002200;">-</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">/</span> tileSize.height<span style="color: #002200;">&#41;</span>;
&nbsp;
  <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> row <span style="color: #002200;">=</span> firstRow; row &lt;<span style="color: #002200;">=</span> lastRow; row<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> col <span style="color: #002200;">=</span> firstCol; col &lt;<span style="color: #002200;">=</span> lastCol; col<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
      UIImage <span style="color: #002200;">*</span>tile <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self tileAtCol<span style="color: #002200;">:</span>col row<span style="color: #002200;">:</span>row<span style="color: #002200;">&#93;</span>;
&nbsp;
      CGRect tileRect <span style="color: #002200;">=</span> CGRectMake<span style="color: #002200;">&#40;</span>tileSize.width <span style="color: #002200;">*</span> col, 
                         tileSize.height <span style="color: #002200;">*</span> row,
                         tileSize.width, tileSize.height<span style="color: #002200;">&#41;</span>;
&nbsp;
      tileRect <span style="color: #002200;">=</span> CGRectIntersection<span style="color: #002200;">&#40;</span>self.bounds, tileRect<span style="color: #002200;">&#41;</span>;
&nbsp;
      <span style="color: #002200;">&#91;</span>tile drawInRect<span style="color: #002200;">:</span>tileRect<span style="color: #002200;">&#93;</span>;
&nbsp;
      <span style="color: #11740a; font-style: italic;">// Draw a white line around the tile border so </span>
      <span style="color: #11740a; font-style: italic;">// we can see it</span>
      <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIColor whiteColor<span style="color: #002200;">&#93;</span> set<span style="color: #002200;">&#93;</span>;
      CGContextSetLineWidth<span style="color: #002200;">&#40;</span>context, <span style="color: #2400d9;">6.0</span><span style="color: #002200;">&#41;</span>;
      CGContextStrokeRect<span style="color: #002200;">&#40;</span>context, tileRect<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
  <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Our view port in the app is set by the frame of the scroll view. This view is a lot larger than a single tile, which we have set to the default size of 256 x 256. That means we need to find all of the tiles that need to be drawn for displaying in the view port. So, we calculate the first column, last column, first row, and last row. This tells us where within the image we need to start and stop drawing. It also tells us which tiles we need to load. Once we&#8217;ve got all of these rows and columns calculated, we can then iterate through them and grab the tile for the current row and column using the same filename format we used to save the files in the first place. The code to load the image tiles looks like this:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>UIImage<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tileAtCol<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>col row<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>row
<span style="color: #002200;">&#123;</span>
  <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>path <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@/%@%d_%d.png&quot;</span>, tileDirectory, tileTag, col, row<span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>UIImage imageWithContentsOfFile<span style="color: #002200;">:</span>path<span style="color: #002200;">&#93;</span>;  
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Notice we&#8217;re using -imageWithContentsOfFile rather than -imageNamed, since -imageNamed actually caches the image in memory&#8211;which we don&#8217;t want. If we used that, we would be right back at our memory usage issue after scrolling around for a few minutes.</p>

<h2>Conclusion</h2>

<p>Using the CATiledLayer makes a lot of sense when memory is of the essence, which it is much of the time when doing iOS development. Examples from Apple and other places do a good job showing how you can use a tiled layer for use with PDFs, but if you want to tile an image, things are a little more complicated. I hope this post has served to help you better understand this powerful Core Animation layer. Until next time.</p>

<p><a href="http://www.cimgf.com/files/BitmapSlice.zip">Download Demo Project</a></p>

<h2>Notes on the Demo Project</h2>

<p>When running on the device the image I am tiling is just too large to be tiled completely before the app uses up too much memory and is killed. You will probably want to run in the simulator to see the tiling finish. As noted in the code comments, you un-comment the tiling code and do a first run with the app allowing it to finish tiling. Then, stop the app and re-comment that tiling code and it will just load and display the tiles it created without having to go through that tiling again. I suppose I could have made the tiling code get called in response to a button tap or something like that, but I&#8217;ll leave that as an exercise for the reader. Contact me through the comments below if you have any problems or questions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2011/03/01/subduing-catiledlayer/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Passing around a NSManagedObjectContext on iOS</title>
		<link>http://www.cimgf.com/2011/01/07/passing-around-a-nsmanagedobjectcontext-on-the-iphone/</link>
		<comments>http://www.cimgf.com/2011/01/07/passing-around-a-nsmanagedobjectcontext-on-the-iphone/#comments</comments>
		<pubDate>Fri, 07 Jan 2011 19:23:46 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Coding Practice]]></category>
		<category><![CDATA[Core Data]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPod Touch]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=1274</guid>
		<description><![CDATA[This article is reprinted from the MDN The documentation on Core Data for the iPhone has lead to some confusion about how best to use Core Data on a Cocoa Touch device. One particular section seems to be the most confusing, specifically: A view controller typically shouldn’t retrieve the context from a global object such [...]]]></description>
			<content:encoded><![CDATA[<p><strong>This article is reprinted from the MDN</strong></p>

<p>The documentation on Core Data for the iPhone has lead to some confusion about how best to use Core Data on a Cocoa Touch device.  One particular section seems to be the most confusing, specifically:</p>

<blockquote>
  <p>A view controller typically shouldn’t retrieve the context from a global object such as the application delegate. This tends to make the application architecture rigid. Neither should a view controller typically create a context for its own use. This may mean that operations performed using the controller’s context aren’t registered with other contexts, so different view controllers will have different perspectives on the data.</p>
  
  <p>When you create a view controller, you pass it a context. You pass an existing context, or (in a situation where you want the new controller to manage a discrete set of edits) a new context that you create for it. It’s typically the responsibility of the application delegate to create a context to pass to the first view controller that’s displayed.</p>
</blockquote>

<p>The idea behind this section is the issue of rigidity.  Ideally, each view controller should be an island on its own.  It should not rely on its parent, nor should it rely on the Application Delegate.  Once a view controller is pushed onto the screen it should ideally be its own master.</p>

<h2>Why Rigidity is bad</h2>

<p>It is fairly common when designing a Cocoa Touch application to &#8220;hard code&#8221; everything.  Take the following navigation controller design:</p>

<p><img src="http://www.cimgf.com/wp-content/uploads/2011/01/Image1.png" alt="Navigation Controller Design" title="Standard Navigation Controller Design" /></p>

<p>When this design, it is common to code each view controller and make it &#8220;aware&#8221; of its parent.  In that design, it would be common to see view controller B call methods or call back (to its delegate) view controller A.  While there is nothing technically wrong with this design, it is very rigid.  It is nearly impossible to either move view controller B to another location in the stack or to reuse view controller B somewhere else.  This is the trap that the documentation is trying to help new developers avoid.</p>

<h2>Solution One</h2>

<p>Again using a standard/normal navigation controller design, it is expected that the detail flows from left to right.  The left most (or root) view controller contains the most vague information and the right most (or deepest) view controller contains the greatest detail.</p>

<p><img src="http://www.cimgf.com/wp-content/uploads/2011/01/Image2.png" alt="UIFetchedResultsController" title="UIFetchedResultsController" /></p>

<p>In this case then the best solution is to use a <code>UIFetchedResultsController</code>.  This controller can be considered a thin layer between the view controllers and the Core Data bits.  The advantage is that the <code>UIFetchedResultsController</code> is designed to work with tables.  The other advantage is that your least detailed view (the root most likely) can listen as the delegate of the <code>UIFetchedResultsController</code> for changes and update itself.</p>

<p>In this design, however, instead of passing around a context, you would hand off just the entity that the child view controller needs to know about.  The Core Data Recipes example provided by Apple illustrates this design quite well.</p>

<p>How does this break rigidity?  Each view controller, from the root on down, only knows what is passed into it.  The root gets the <code>UIFetchedResultsController</code> passed into it.  The child views only get the items it cares about passed into it.  None of them care what their parent view controller is.  There is no call back to a parent.</p>

<h2>Solution two</h2>

<p>What happens when we don&#8217;t have a typical navigation controller design?  Perhaps a child view can pop up a modal view that displays different information.  Perhaps a child view, for whatever reason needs to access information that cannot be directly passed into it every time.</p>

<p>In these cases there are a few different options.</p>

<h3>View already has a <code>NSManagedObject</code></h3>

<p>Following our example above, lets say that view controller C needs to create a new object.  Perhaps it is a detail view of a recipe and the user wants to add a new recipe type (perhaps she is a vegan and just discovered there is no vegan type in the list).  In this case we have passed in an entity (the recipe) but not a reference to the <code>NSManagedObjectContext</code>.  Fortunately this solution is easy to fix.  The <code>NSManagedObject</code> retains a reference to its <code>NSManagedObjectContext</code> internally and we can access it.  Therefore we can easily retrieve the <code>NSManagedObjectContext</code> from the <code>NSManagedObject</code> and create the new Type entity and pass it to the modal child or whatever our design calls for.</p>

<p>This again avoids rigidity because the view controller that represents the entity does not need to call up to a parent object or the <code>UIApplication</code> delegate.  It is self contained and only manages view controllers that are down stream from it.</p>

<h3>View does not have a <code>NSManagedObject</code></h3>

<p>In this situation things are <em>slightly</em> more complicated.  In this case we want to create a <code>@property</code> for the <code>NSManagedObjectContext</code> and require that our creator set the property.</p>

<pre><code>@interface MyViewController : ViewController
{
    NSManagedObjectContext *moc;
}

@property (nonatomic, retain) NSManagedObjectContext *moc;

@end
</code></pre>

<p>Again, the view controller is an island of its own because it does not care where that <code>NSManagedObjectContext</code> came from.  All it knows is that it is required for the view to function.  It does not care of it is a new <code>NSManagedObjectContext</code> specifically created for its use (perhaps for a cancelable edit tree) or if it is the same <code>NSManagedObjectContext</code> that has been passed around since the launch of the application.  All it knows is that it has the elements it needs to perform its function.</p>

<p>By making the <code>NSManagedObjectContext</code> a settable property we can also transplant the view easily.  If, at some point in the project lifecycle, we decide that it makes more sense to have the following design:</p>

<p><img src="http://www.cimgf.com/wp-content/uploads/2011/01/Image3.png" alt="Modal View Controller" title="Modal View Controller" /></p>

<p>Taking from Apple&#8217;s Recipes Application, perhaps we decide that moving from the table view directly to the image of the recipe is more pleasing to the users and that when they want to see how to make it they can &#8220;flip&#8221; the image over and see the detail.</p>

<p>Making this change with each view controller being an island is quite simple.  We just rearrange the views without having to worry too much about breaking the application.</p>

<h2>Solution three</h2>

<p>Up until now we have been looking at just a navigation controller design.  But what about tab bars?  In the situation of a tab bar we again want to avoid rigidity because it is even more common that tabs will get moved around.</p>

<p>The solution to this is to again use a <code>@property</code> for the <code>NSManagedObjectContext</code> and require that the creator set this property before the view is displayed on screen.  If you are creating the tabs in code this is trivial because you are already calling init on the view controller and you can add one more line of code after the init to set the property.</p>

<p>If the user interface is being developed mostly in Interface Builder it is slightly more tricky.  Personally I am not a fan of creating navigation controllers or tab bar controllers in Interface Builder.  However if that is the design then I would recommend referencing the view controllers as properties and passing along the context upon initialization of the application.  It may be possible to do this entirely in Interface Builder but I am not comfortable enough to recommend that as a solution.</p>

<h2>Conclusion</h2>

<p>The overall idea behind this article is to keep each view controller separate from anything up stream or in a different silo.  This will make the design far more flexible in the long run.  Any time that you feel the &#8220;need&#8221; to pass in a parent view controller to a child view controller, reconsider the design.  Consider using a <code>@protocol</code> delegate design or NSNotification calls instead.  Keep each view controller as its own private island.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2011/01/07/passing-around-a-nsmanagedobjectcontext-on-the-iphone/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>View Your iPhoto Library From Your iPad [UPDATED]</title>
		<link>http://www.cimgf.com/2010/06/23/view-your-iphoto-library-from-your-ipad/</link>
		<comments>http://www.cimgf.com/2010/06/23/view-your-iphoto-library-from-your-ipad/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 07:31:26 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[AppStore]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=1138</guid>
		<description><![CDATA[Announcing PhotoGrab for iPad! I wrote this little utility app that allows you to browse your iPhoto library shares across your wifi network and download and save either a hi-res version of your photos or a version resized especially for display on iPad. It features multi-download as well as a slideshow mode. Just share your [...]]]></description>
			<content:encoded><![CDATA[<p>Announcing <a href="http://photograb.skyeroadsystems.com/">PhotoGrab for iPad</a>! I wrote this little utility app that allows you to browse your iPhoto library shares across your wifi network and download and save either a hi-res version of your photos or a version resized especially for display on iPad. It features multi-download as well as a slideshow mode. Just share your photos from within your iPhoto preferences sharing tab and you will be able to access your photos across the network from your iPad.</p>

<p>I wrote the app because I don&#8217;t sync my iPad with the computer where we store all of our photos, but from time to time I like to grab a photo from the iPhoto library without having to sync.</p>

<p>I just submitted a new point release that fixes a few crashers and other bugs to the App Store, but go ahead and take a look at this one and let me know what you think.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/06/appstore01.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/06/appstore01-300x225.png" alt="" title="appstore01" width="300" height="225" class="alignleft size-medium wp-image-1125" /></a></p>

<h2>Free Promo Codes!</h2>

<p>Just for the readers of this site! If you&#8217;re interested in the app, send an email to <em>promocodes at cimgf dot com</em> with the subject line <strong>PhotoGrab Promo Codes</strong>. I will send an email containing a promo code to the first 50 I receive (since the Apple only issues 50 of them per version). Be patient with me as I will be responding manually as I receive the messages. It will be first come, first served. Otherwise, check it out in the App Store. Promo codes are <strong>only valid in the US App Store</strong>.</p>

<h2 style="color:red">Update on Promo Codes</h2>

<p>I have received a lot of email requests for promo codes and will be sending them to the first 50 by the end of the day today (06/23/2010). If you do not receive a code by the end of the day, you were not in the first batch. When the next release hits the App Store, I will have another 50 at my disposal and will send those to the next group. Thanks for your interest.</p>

<p><a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=373208325&#038;mt=8"><img src="http://photograb.skyeroadsystems.com/wp-content/uploads/2010/05/appstorebadge.png" border="0"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2010/06/23/view-your-iphoto-library-from-your-ipad/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Differentiating Tap Counts on iOS [UPDATED]</title>
		<link>http://www.cimgf.com/2010/06/14/differentiating-tap-counts-on-ios/</link>
		<comments>http://www.cimgf.com/2010/06/14/differentiating-tap-counts-on-ios/#comments</comments>
		<pubDate>Mon, 14 Jun 2010 23:02:08 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPod Touch]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=1072</guid>
		<description><![CDATA[In your iPhone/iPad apps you often need to know how many times your user tapped in a view. This can be challenging because, though the user may have tapped twice, you will receive the event and it will look like they tapped once as well as twice. If the user triple-tapped, you will get the [...]]]></description>
			<content:encoded><![CDATA[<p>In your iPhone/iPad apps you often need to know how many times your user tapped in a view. This can be challenging because, though the user may have tapped twice, you will receive the event and it will look like they tapped once as well as twice. If the user triple-tapped, you will get the event for one tap, two taps, and three taps. It can get a little frustrating, but the trick is timing. You simply have to wait a period of time to see if another tap comes. If it does, you cancel the action spawned by the first tap. If it doesn&#8217;t you allow the action to run. There&#8217;s a few little nuances to getting it to work, but it can be done. Here is how.
<span id="more-1072"></span></p>

<h2>Overriding Touch Event Handlers</h2>

<p>In order to know how many times your user tapped, you listen for the events in the various touch handlers. Let start with -touchesEnded. This is where we will determine how many taps we received and respond accordingly. Consider the following code.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>touchesEnded<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSSet</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>touches withEvent<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIEvent<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>event 
<span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>touches.count <span style="color: #002200;">==</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span>
  <span style="color: #002200;">&#123;</span>  
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>touches anyObject<span style="color: #002200;">&#93;</span> tapCount<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>self handleDoubleTap<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>touches anyObject<span style="color: #002200;">&#93;</span> tapCount<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #2400d9;">3</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>self handleTripleTap<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span>
    <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>self handleSingleTap<span style="color: #002200;">&#93;</span>; 
    <span style="color: #002200;">&#125;</span>
  <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>If you place a breakpoint inside each of the code blocks for the three tap counts, you will find that in the case where you triple tap, it will break in all three. If you double tap, it will break in both the double tap and single tap and of course if you single tap, it will break in the single tap branch.</p>

<p>In most cases, this is not desirable. You will likely want a clean differentiation between each touch as each tap count will likely mean something different. So how can we fix this? The trick is to use <em>-peformSelector:withObject:afterDelay</em> and then canceling the perform action if a new action occurs. Got it?</p>

<h2>Wait For It&#8230;</h2>

<p>If you call the method directly as we did in the sample code above, there is no way to delay when it runs nor is there a way to cancel it should another tap be received. Both of these things are necessary. If you think about it, waiting to run our <em>-handleSingleTap</em> method until a certain amount of time passes helps make sure it actually was a double tap. If the user taps once and nothing else occurs, we&#8217;re safe to run the <em>-handleSingleTap</em> code. If another tap is received in the mean time, however, we can cancel the action from the first tap. The way we do this is by changing our <em>-touchesEnded:</em> code to something like this:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>touchesEnded<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSSet</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>touches withEvent<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIEvent<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>event 
<span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>touches.count <span style="color: #002200;">==</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span>
  <span style="color: #002200;">&#123;</span>  
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>touches anyObject<span style="color: #002200;">&#93;</span> tapCount<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>self performSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>handleDoubleTap<span style="color: #002200;">&#41;</span>
                 withObject<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span>
                 afterDelay<span style="color: #002200;">:</span><span style="color: #2400d9;">0.35</span><span style="color: #002200;">&#93;</span>; 
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>touches anyObject<span style="color: #002200;">&#93;</span> tapCount<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #2400d9;">3</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>self handleTripleTap<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span>
    <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>self performSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>handleSingleTap<span style="color: #002200;">&#41;</span>
                 withObject<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span>
                 afterDelay<span style="color: #002200;">:</span><span style="color: #2400d9;">0.35</span><span style="color: #002200;">&#93;</span>; 
    <span style="color: #002200;">&#125;</span>
  <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Notice that we are delaying 350 milliseconds to see if another event occurs. You should also notice that we still call <em>-handleTripleTap</em> directly without using <em>-performSelector:withObject:afterDelay</em>. This is because it has now been isolated as a distinct event. If we get a triple tap, we&#8217;re pretty well assured now that a double or single tap event was not actually run as those events will have been cancelled. So how does that work? How do we cancel them?</p>

<h2>Canceling The Action</h2>

<p>Now that we are waiting around to see if another tap event occurs, we need to override the <em>-touchesBegan:</em> method. It will look something like this:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>touchesBegan<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSSet</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>touches withEvent<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIEvent<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>event
<span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSObject</span> cancelPreviousPerformRequestsWithTarget<span style="color: #002200;">:</span>self
                                           selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>handleSingleTap<span style="color: #002200;">&#41;</span>
                                             object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSObject</span> cancelPreviousPerformRequestsWithTarget<span style="color: #002200;">:</span>self
                                           selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>handleDoubleTap<span style="color: #002200;">&#41;</span>
                                             object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>The method <em>-cancelPreviousPerformRequestsWithTarget:selector:object:</em> is able to determine which action you want to cancel and then cancel it preventing the selectors, <em>-handleSingleTap</em> or <em>-handleDoubleTap</em> from being called&#8211;assuming the second or third taps occurred within the allocated 350 milliseconds. That&#8217;s all there is to it.</p>

<h2>There *Is* a Catch</h2>

<p>That is all there is to it, however, you have to be careful if you intend to pass parameters to your selectors. If you use a selector that takes a parameter so that you have to call something with <em>-performSelector:withObject:afterDelay:</em> passing an object to the second parameter, you will need <em>that</em> object or one identical to it in your call to cancel the action with <em>-cancelPreviousPerformRequestsWithTarget:selector:object:</em>. It must be able to evaluate to true when <em>equals</em> is called on the object passed into the <em>object</em> parameter. This can be tricky, but you can overcome it in one of two ways using an ivar:</p>

<ul>
<li><p>Create an ivar to hold onto the variable that you will use as a parameter to the cancel when you first pass it to the <em>-performSelector:withObject:afterDelay:</em> call.</p></li>
<li><p>Create an ivar to hold onto the variable when you first enter touches ended and call <em>-performSelector:withObject:afterDelay</em> passing it nil for the <em>object</em> parameter. Then, grab the ivar when you need it in your handler code. The cancel call can then take nil for its <em>object</em> parameter.</p></li>
</ul>

<p>These points are crucial if you are intending to pass parameters as the cancel will fail if you try to pass a parameter and it doesn&#8217;t match what you used in your call to <em>-performSelector:withObjecct:afterDelay:</em>. The only parameter that doesn’t matter is the <em>afterDelay:</em> param.</p>

<h2>Conclusion</h2>

<p>I&#8217;m finding the need to differentiate tap counts more and more often so this post is really as much a way for me to keep a journal of things I need to do frequently as it is to help others figure things out too. I hope it&#8217;s been helpful to you. Until next time.</p>

<h1>Update</h1>

<p>So, apparently Gesture Recognizers do address this issue. I had looked at them as a possible solution, but ran into the same differentiation problems, hence this blog post. However, <a href="http://twitter.com/aclark">Ashley Clark</a> pointed me to the <em><a href="http://developer.apple.com/iphone/library/documentation/uikit/reference/UIGestureRecognizer_Class/Reference/Reference.html#//apple_ref/occ/instm/UIGestureRecognizer/requireGestureRecognizerToFail:">-requireGestureRecognizerToFail:</a></em> method, which apparently enables you to have this cancellation functionality by creating a dependency between recognizers. The code to take advantage of it looks something like this:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;">UITapGestureRecognizer <span style="color: #002200;">*</span>tripleTap <span style="color: #002200;">=</span> 
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UITapGestureRecognizer alloc<span style="color: #002200;">&#93;</span>
 initWithTarget<span style="color: #002200;">:</span>self action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>handleTripleTap<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>tripleTap setNumberOfTapsRequired<span style="color: #002200;">:</span><span style="color: #2400d9;">3</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self view<span style="color: #002200;">&#93;</span> addGestureRecognizer<span style="color: #002200;">:</span>tripleTap<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>tripleTap release<span style="color: #002200;">&#93;</span>;
&nbsp;
UITapGestureRecognizer <span style="color: #002200;">*</span>doubleTap <span style="color: #002200;">=</span> 
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UITapGestureRecognizer alloc<span style="color: #002200;">&#93;</span>
 initWithTarget<span style="color: #002200;">:</span>self action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>handleDoubleTap<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>doubleTap setNumberOfTapsRequired<span style="color: #002200;">:</span><span style="color: #2400d9;">2</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>doubleTap requireGestureRecognizerToFail<span style="color: #002200;">:</span>tripleTap<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self view<span style="color: #002200;">&#93;</span> addGestureRecognizer<span style="color: #002200;">:</span>doubleTap<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>doubleTap release<span style="color: #002200;">&#93;</span>;
&nbsp;
UITapGestureRecognizer <span style="color: #002200;">*</span>singleTap <span style="color: #002200;">=</span> 
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UITapGestureRecognizer alloc<span style="color: #002200;">&#93;</span>
 initWithTarget<span style="color: #002200;">:</span>self action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>handleSingleTap<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>singleTap setNumberOfTapsRequired<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// Unnecessary since it's the default</span>
<span style="color: #002200;">&#91;</span>singleTap requireGestureRecognizerToFail<span style="color: #002200;">:</span>doubleTap<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self view<span style="color: #002200;">&#93;</span> addGestureRecognizer<span style="color: #002200;">:</span>singleTap<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>singleTap release<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>


<p>So, if your project is 3.2 and later, use gesture recognizers. The effect is about the same, but the code is quite a bit cleaner.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2010/06/14/differentiating-tap-counts-on-ios/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Fixing the UISplitViewController Template</title>
		<link>http://www.cimgf.com/2010/05/24/fixing-the-uisplitviewcontroller-template/</link>
		<comments>http://www.cimgf.com/2010/05/24/fixing-the-uisplitviewcontroller-template/#comments</comments>
		<pubDate>Mon, 24 May 2010 16:37:18 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=1019</guid>
		<description><![CDATA[The default implementation of the UISplitViewController based template in Xcode does not provide a navigation controller stack in the detail view. Instead it is just a regular old view with a navigation bar at the top. I suppose there are cases when you might want such an implementation, however, i think you would more commonly [...]]]></description>
			<content:encoded><![CDATA[<p>The default implementation of the UISplitViewController based template in Xcode does not provide a navigation controller stack in the detail view. Instead it is just a regular old view with a navigation bar at the top. I suppose there are cases when you might want such an implementation, however, i think you would more commonly want there to be a navigation stack for cases when you wan to push new view controllers for your users to see. In this post i intend to demonstrate how to convert the default template to something more useable.
<span id="more-1019"></span></p>

<h2>Gut The Default Template</h2>

<p>It&#8217;s not quite as drastic as the work &#8216;gut&#8217; might imply, but you want to remove some things from the default template nib. To get started create a Split View project, by selecting <strong>File | New Project&#8230;</strong> in Xcode. Then choose <strong>Split View-based Application</strong> and click <strong>Choose&#8230;</strong>. Name your application. I called mine <strong>&#8216;SpiffySplitView&#8217;</strong>.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/splitviewproject.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/splitviewproject-300x240.png" alt="" title="splitviewproject.png" width="300" height="240" class="alignleft size-medium wp-image-1020" /></a></p>

<p>Double-click <em>DetailView.xib</em> under the Resources group in your newly created project. This will open Interface Builder.</p>

<p>The first thing you will notice in the Interface Builder editor is that there is a UINavigationBar at the top. Select this bar and delete it. We will be switching the detail view of this split view project to use a UINavigationController which will add this nav bar back in for us but will provide the whole navigation stack along with it providing us the flexibility to push new view controllers in the detail view.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/detailsview.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/detailsview-271x300.png" alt="" title="detailsview.png" width="271" height="300" class="alignleft size-medium wp-image-1022" /></a></p>

<p>In the View inspector you will also want to make the Orientation Landscape, make the Top Bar a Navigation Bar, and set the Split View option to &#8220;Detail&#8221;.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/viewattribs.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/viewattribs-300x233.png" alt="" title="viewattribs" width="300" height="233" class="alignleft size-medium wp-image-1047" /></a></p>

<p>Once you have made these changes, save the nib and switch back to Xcode. Now, double click the <em>MainWindow.xib</em> file in the Resources section of your Xcode project which will open it in Interface Builder.</p>

<h2>Implementing a Navigation Controller In The Detail View</h2>

<p>When <em>MainWindow.xib</em> opens in Interface Builder, take a look at the MainWindow.xib resources and switch to the detailed list view if you haven&#8217;t already so that the window looks something like this:</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/splitviewcontrollercontrollers.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/splitviewcontrollercontrollers-300x227.png" alt="" title="splitviewcontrollercontrollers" width="300" height="227" class="alignleft size-medium wp-image-1032" /></a></p>

<p>Notice that the Split View Controller contains two view controllers. The first one is a navigation controller, but the second one is our detail view controller. The first thing you want to do is change that. From the Library palette in Interface Builder, select the Navigation Controller object and drag and drop it on top of the detail view controller in the resources window.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/dropnavcontroller.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/dropnavcontroller-300x246.png" alt="" title="dropnavcontroller" width="300" height="246" class="alignleft size-medium wp-image-1033" /></a></p>

<p>The detail view controller will automatically switch to a navigation controller. Now you need to twirl down the new nav controller and change the root view controller type to a DetailViewController by switching to the Identity tab in the inspector.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/detailviewinnavcontroller.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/detailviewinnavcontroller-300x160.png" alt="" title="detailviewinnavcontroller" width="300" height="160" class="alignleft size-medium wp-image-1034" /></a></p>

<p>Finally we are going to need to make our new navigation controller a delegate of the UISplitViewController in order to receive split view change notifications. Drag a connection from the Split View Controller to the Detail View Controller and select <strong>delegate</strong>.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/splitviewdelegate.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/splitviewdelegate-300x250.png" alt="" title="splitviewdelegate" width="300" height="250" class="alignleft size-medium wp-image-1036" /></a></p>

<p>Save your work. If you switch back to Xcode and run the application, you may not notice much of a difference in the look of the application, however, we can now make some changes in code that will give us a lot more flexibility.</p>

<h2>Changes In Code</h2>

<p>Edit DetailViewController.m in Xcode and change the -viewDidLoad method to set a title for the view controller. This will get passed up to the navigation controller which will display the title in the navigation bar.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad
<span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>self setTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Spiffy&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>This code will allow you to see the word &#8216;Spiffy&#8217; in the navigation bar.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/spiffytitle.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/spiffytitle-300x252.png" alt="" title="spiffytitle" width="300" height="252" class="alignleft size-medium wp-image-1038" /></a></p>

<p>Next, you will notice that in portrait view, we have no button to tap to see our table view. It is only available in landscape view. To remedy this, you need to change a few lines of code&#8211;again in the DetailViewController you will modify the split view delegate methods. These methods simple add and remove the bar button item depending upon which mode we&#8217;re in, landscape or portrait or more specifically whether we are showing or hiding our list view controller.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>splitViewController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UISplitViewController<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>svc 
     willHideViewController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIViewController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>aViewController 
          withBarButtonItem<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIBarButtonItem<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>barButtonItem 
       forPopoverController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIPopoverController<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>pc
<span style="color: #002200;">&#123;</span>  
  <span style="color: #002200;">&#91;</span>barButtonItem setTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Root List&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self navigationItem<span style="color: #002200;">&#93;</span> setLeftBarButtonItem<span style="color: #002200;">:</span>barButtonItem<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>self setPopoverController<span style="color: #002200;">:</span>pc<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>splitViewController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UISplitViewController<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>svc 
     willShowViewController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIViewController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>aViewController 
  invalidatingBarButtonItem<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIBarButtonItem <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>barButtonItem
<span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self navigationItem<span style="color: #002200;">&#93;</span> setLeftBarButtonItem<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>self setPopoverController<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Now you can see our button show and hide correctly.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/buttonisvisible.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/buttonisvisible-235x300.png" alt="" title="buttonisvisible" width="235" height="300" class="alignleft size-medium wp-image-1040" /></a></p>

<p>A problem you my run into now is that when you select one of the items in the list view, the detail view doesn&#8217;t actually update. This is due to the fact that we disconnected things when we changed our detail view controller in the split view to a navigation controller and we never re-connected it. To re-connect, open MainWindow.xib in Interface Builder again by double clicking it from the Resources group in Xcode. Then drag a connection from the root view controller to the Detail View Controller and select <strong>detailViewController</strong>.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/detailviewoutlet.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/detailviewoutlet-300x227.png" alt="" title="detailviewoutlet" width="300" height="227" class="alignleft size-medium wp-image-1070" /></a></p>

<h2>The Point</h2>

<p>So now what? The project is, in essence, now back to where it was when we started, right? Except now we can push new view controllers onto the stack. To demonstrate this, let&#8217;s add a button to the detail view controller that will be the trigger for pushing a new view controller and then we can create the new view controller to push.</p>

<p>In Xcode, create an action in the detail view controller that we will connect to. The code will look something like this.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>pushNewViewController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
  <span style="color: #11740a; font-style: italic;">// Create and push new view controller here</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>In Xcode, double click the DetailView.xib to open it in Interface Builder. Then add a button to the view. Drag a connection from the new button to the action we just created.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/pushnewview.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/pushnewview-300x222.png" alt="" title="pushnewview" width="300" height="222" class="alignleft size-medium wp-image-1045" /></a></p>

<p>Save your changes and go back into Xcode. Select <strong>File | New File&#8230;</strong>. In the ensuing dialog, choose <strong>UIViewController subclass</strong> in the <strong>Cocoa Touch Class</strong> group and make sure you have <strong>Targeted for iPad</strong> and <strong>With XIB for user interface</strong> selected. Click Next and then provide a name. I called my <em>NewViewController</em>.</p>

<p>Double-click the <em>NewViewController.xib</em> file to open it in Interface Builder. Change the settings on the view to do the following:</p>

<ul>
<li>Set orientation to landscape</li>
<li>Set Top Bar to Navigation Bar</li>
<li>Set Split View to Detail</li>
</ul>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/viewattribs.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/viewattribs-300x233.png" alt="" title="viewattribs" width="300" height="233" class="alignleft size-medium wp-image-1047" /></a></p>

<p>Save your changes and switch back to Xcode. In the -viewDidLoad of your NewViewController.m file, set the title again.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad
<span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>self setTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;New View Controller&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Now, in your DetailViewController.m file, #import the NewViewController.h file and then implement the push new view controller action.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>pushNewViewController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
  <span style="color: #11740a; font-style: italic;">// Create and push new view controller here</span>
  NewViewController <span style="color: #002200;">*</span>controller <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NewViewController alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self navigationController<span style="color: #002200;">&#93;</span> pushViewController<span style="color: #002200;">:</span>controller animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>controller release<span style="color: #002200;">&#93;</span>, controller <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Now, when you tap the button on the detail view controller, a NewViewController will be pushed onto the navigation stack.</p>

<h2>Conclusion</h2>

<p>There are certainly legitimate reasons to place a navigation bar into your view manually. You might want to just use it as a place for tool bar items or other information. You may not need the navigation controller stack functionality, but providing yourself a way to push a new view controller on the navigation stack opens up additional possibilities while retaining the capabilities you have by using only a navigation bar. As the kids say, &#8220;it&#8217;s all good&#8221;. Until next time.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2010/05/SpiffySplitView.zip'>SpiffySplitView Xcode Project</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2010/05/24/fixing-the-uisplitviewcontroller-template/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Creating a NSManagedObject that is Cross Platform</title>
		<link>http://www.cimgf.com/2010/02/18/creating-a-nsmanagedobject-that-is-cross-platform/</link>
		<comments>http://www.cimgf.com/2010/02/18/creating-a-nsmanagedobject-that-is-cross-platform/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 18:37:33 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[Coding Practice]]></category>
		<category><![CDATA[Core Data]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPod Touch]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=950</guid>
		<description><![CDATA[An interesting question came up on Stackoverflow today so I decided to expound upon it in a short blog post. A situation that I believe we are going to be seeing more and more often is one where application developers are writing multiple &#8220;versions&#8221; of their applications to be used on the desktop, their iPhone [...]]]></description>
			<content:encoded><![CDATA[<p>An interesting question came up on Stackoverflow today so I decided to expound upon it in a short blog post.</p>

<p>A situation that I believe we are going to be seeing more and more often is one where application developers are writing multiple &#8220;versions&#8221; of their applications to be used on the desktop, their iPhone and now the iPad.</p>

<p>Because of that situation, it is becoming even more important that we write as much portable code as possible.  Fortunately, our model can be completely portable between the two platforms.</p>

<p><span id="more-950"></span></p>

<h2>NSImage vs UIImage</h2>

<p>The primary issue with creating a portable model and model objects is images.  Now, if the images are stored on disk and only referenced in your Core Data model, then you don&#8217;t have an issue.  Since you are storing the images on disk in a portable format (png, jpeg, etc.) then they will port right over to all of the platforms you are targeting.</p>

<p>But what happens when you are working with small images that should be stored within Core Data?  Simple right, just use a transformable data type and stick the image right in there.</p>

<p>Unfortunately that fails in the portability department.</p>

<p>The issue is that on the desktop you are storing a serialized version of the NSImage instance and on the other devices you are storing an instance of UIImage.  Two different data structures that are incompatible.  So what is the right answer?</p>

<p>Store the images in a portable format even in Core Data.</p>

<p>But that is hard right?</p>

<p>Fortunately if we create concrete subclasses of any entity that needs to store images it is a small amount of code and some conditional compiling.</p>

<h3><code>MyEntityWithAnImage.h</code></h3>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;">&nbsp;
<span style="color: #a61390;">@interface</span> MyEntityWithAnImage <span style="color: #002200;">:</span> <span style="color: #400080;">NSManagedObject</span>
<span style="color: #002200;">&#123;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#ifdef IPHONEOS_DEPLOYMENT_TARGET</span>
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> UIImage <span style="color: #002200;">*</span>image;
<span style="color: #6e371a;">#else</span>
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> <span style="color: #400080;">NSImage</span> <span style="color: #002200;">*</span>image;
<span style="color: #6e371a;">#endif</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<p>In the header we declare the same property and the use some conditional compiling to determine which definition should be used.  On the desktop the property image will return an NSImage and on the other platforms it will return a UIImage.  But how do we work this magic?</p>

<h3><code>MyEntityWithAnImage.m</code></h3>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#ifdef IPHONEOS_DEPLOYMENT_TARGET</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setImage<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIImage<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image
<span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span>self willChangeValueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>data <span style="color: #002200;">=</span> UIImagePNGRepresentation<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>;
  <span style="color: #002200;">&#91;</span>myManagedObject setImage<span style="color: #002200;">:</span>data<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>self setPrimitiveValue<span style="color: #002200;">:</span>data forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>self didChangeValueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>UIImage<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image
<span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span>self willAccessValueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span>;
  UIImage <span style="color: #002200;">*</span>image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIImage imageWithData<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self primitiveValueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>self didAccessValueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">return</span> image;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#else</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setImage<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSImage</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image
<span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span>self willChangeValueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #400080;">NSBitmapImageRep</span> <span style="color: #002200;">*</span>bits <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>image representations<span style="color: #002200;">&#93;</span> objectAtIndex<span style="color: #002200;">:</span> <span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>data <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>bits representationUsingType<span style="color: #002200;">:</span>NSPNGFileType properties<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>myManagedObject setImage<span style="color: #002200;">:</span>data<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>self setPrimitiveValue<span style="color: #002200;">:</span>data forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>self didChangeValueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSImage</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image
<span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span>self willAccessValueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #400080;">NSImage</span> <span style="color: #002200;">*</span>image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSImage</span> alloc<span style="color: #002200;">&#93;</span> initWithData<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self primitiveValueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>self didAccessValueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;image&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>image autorelease<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#endif</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<p>Here we are overriding the dynamic accessors and implementing our own.  We are fully KVO compliant and notify when we are accessing or changing the image value.</p>

<p>In the desktop version we grab the bitmap image representation and then get the PNG representation of it and store that representation into Core Data as NSData.</p>

<p>In the Cocoa Touch version we are using the C function which returns the PNG representation of the UIImage instance directly.  We are again storing that as NSData into our image property.</p>

<p>In both cases the getter reverses the process by loading the NSData back into the appropriate image instance.</p>

<h2>Wrap Up</h2>

<p>This makes the code external to our <code>NSManagedObject</code> completely unaware of the actual data storage and they just know that they are getting back the object they need to work with.</p>

<p>BTW, if anyone knows of another pre-processor variable that I should be using for this instead of <code>IPHONEOS_DEPLOYMENT_TARGET</code> please let me know.  I am not 100% confident that <code>IPHONEOS_DEPLOYMENT_TARGET</code> is the best variable to be testing against.</p>

<p>Do you like this idea, hate it?  Tell me in person at <a href='http://nsconference.com/'>NSConferenceUSA</a>!  Tickets are still available and it will be great to see you there.</p>

<p>If that is too soon then please catch me at <a href='http://360idev-MarcusZ.eventbrite.com/'>360 iDev</a> in April!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2010/02/18/creating-a-nsmanagedobject-that-is-cross-platform/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Getting &#8220;Real Work&#8221; Done</title>
		<link>http://www.cimgf.com/2010/01/30/getting-real-work-done/</link>
		<comments>http://www.cimgf.com/2010/01/30/getting-real-work-done/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 21:02:50 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[iPad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Rants]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=899</guid>
		<description><![CDATA[I had to post a link to this one as well as Fraser does such a great job explaining why the iPad is so compelling . From Fraser&#8217;s post: The tech industry will be in paroxysms of future shock for some time to come. Many will cling to their January-26th notions of what it takes [...]]]></description>
			<content:encoded><![CDATA[<p>I had to post a <a href="http://speirs.org/blog/2010/1/29/future-shock.html">link to this one as well</a> as Fraser does such a great job explaining why the iPad is so compelling . From Fraser&#8217;s post:</p>

<blockquote>The tech industry will be in paroxysms of future shock for some time to come. Many will cling to their January-26th notions of what it takes to get &#8220;real work&#8221; done; cling to the idea that the computer-based part of it is the &#8220;real work.&#8221;
<br /><br />
It&#8217;s not. The Real Work is not formatting the margins, installing the printer driver, uploading the document, finishing the PowerPoint slides, running the software update or reinstalling the OS.
<br /><br />
<strong>The Real Work is teaching the child, healing the patient, selling the house, logging the road defects, fixing the car at the roadside, capturing the table&#8217;s order, designing the house and organizing the party.</strong>
</blockquote>

<p>Exactly! The iPad is genius and it will revolutionize not just books, magazines, etc., but it will revolutionize computing as we know it. I don&#8217;t know about you, but I&#8217;ve got the new SDK fired up and ready to start rocking some apps and it is a very exciting new platform!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2010/01/30/getting-real-work-done/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

