<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Ray Wenderlich</title>
	
	<link>http://www.raywenderlich.com</link>
	<description>Tutorials for iPhone / iOS Developers and Gamers</description>
	<lastBuildDate>Wed, 16 May 2012 13:48:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/RayWenderlich" /><feedburner:info uri="raywenderlich" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Readers App Reviews – May 2012</title>
		<link>http://feedproxy.google.com/~r/RayWenderlich/~3/JoKKG3AD25A/readers-app-reviews-may-2012</link>
		<comments>http://www.raywenderlich.com/13563/readers-app-reviews-may-2012#comments</comments>
		<pubDate>Tue, 15 May 2012 15:00:35 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[apps]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[reviews]]></category>

		<guid isPermaLink="false">http://www.raywenderlich.com/?p=13563</guid>
		<description><![CDATA[TweetThis is a post by Reader&#8217;s Apps Reviewer Ryan Poolos, an iOS Developer and founder of Frozen Fire Studios. Checkout [...]<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012">Readers App Reviews &#8211; May 2012</a> is a post from: <a href="http://www.raywenderlich.com">Ray Wenderlich</a></p>
]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton13563" class="tw_button" style="float:left;"><a href="http://twitter.com/share?url=http%3A%2F%2Fbit.ly%2FIOyWtQ&amp;via=rwenderlich&amp;text=Readers%20App%20Reviews%20%26%238211%3B%20May%202012&amp;related=EmperiorEric&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fwww.raywenderlich.com%2F13563%2Freaders-app-reviews-may-2012" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://d1xzuxjlafny7l.cloudfront.net/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><div id="attachment_11023" class="wp-caption alignright" style="width: 260px"><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/03/ReadersAppReviewBadge2.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/03/ReadersAppReviewBadge2.png" alt="Read about some great apps made by fellow readers!" title="Read about some great apps made by fellow readers!" width="250" height="153" class="size-full wp-image-11023" /></a><p class="wp-caption-text">Read about some great apps made by fellow readers!</p></div>
<p><i>This is a post by Reader&#8217;s Apps Reviewer <a href="http://www.raywenderlich.com/about#ryanpoolos">Ryan Poolos</a>, an iOS Developer and founder of <a href="http://frozenfirestudios.com">Frozen Fire Studios</a>. Checkout his latest game, <a href="http://PopArcade.net/CL">Cyborg Livestock</a>. Checkout his latest website, <a href="http://www.getihelp.com">iHelp</a>.</i></p>
<p>Its that time again! May came fast and we&#8217;ve got a ton of apps to show for it. You&#8217;ve all been very busy building some very fun games and useful apps. </p>
<p>This month there are a lot of super addicting games, making it very hard to actually write the reviews instead of playing.  Sorry Ray!  :]</p>
<p>You guys blew away Aprils record for submissions. Over 45 incredible apps came through my inbox this month. Thank you <em>all</em> for your submissions. </p>
<p>As you know by now there&#8217;s only room to post fifteen reviews per month. Remember its not a popularity contest or judging, this is just something we do to help out our readers and build community.  As such, active readers, forum members, and those who submit all the required information gain priority. The apps are not posted in any particular order or rank. Make sure you check out the Honorable mentions to try out the apps I didn&#8217;t have room for!</p>
<p>So get ready to find out about some awesomely fun apps and games by fellow readers!<span id="more-13563"></span></p>
<h2>Bricks Trouble Origins</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/brickstrouble" rel="attachment wp-att-13587"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/brickstrouble-166x250.jpg" alt="" title="brickstrouble" width="166" height="250" class="alignright size-thumbnail wp-image-13587 photo" /></a>Bricks Trouble Origins is ultra addicting.  You&#8217;re a space pilot named Jed, and you like to blow up groups of blocks floating in space.  </p>
<p>Where&#8217;d the blocks come from you ask? Don&#8217;t ask questions private! </p>
<p>The trick is you have to convert uneven clusters of bricks into perfect rectangles so they explode, adding some fun strategy to the game.  </p>
<p>Features Game Center and OpenFeint so you can compete with your friends for high scores as well!</p>
<ul>
<li><em>Author:</em> <a href="http://www.2pgames.com">Pawel Pieciak</a> <a href="http://twitter.com/2PGames">@2PGames</a></li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/2797/introduction-to-in-app-purchases">Introduction to In-App Purchases</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fapp%252Fbricks-trouble-origins%252Fid462206809%253Fmt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Particulate</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/particulate" rel="attachment wp-att-13592"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/particulate-166x250.png" alt="" title="particulate" width="166" height="250" class="alignright size-thumbnail wp-image-13592 photo" /></a>Particulate is a a fun tool for creating beautiful particle systems on your iPhone. </p>
<p>It&#8217;s very fun to play around with but it&#8217;s also very powerful. It even has the ability to layer multiple particles from a single emitter!</p>
<p>Performance in my experiments was very impressive as I pushed my aging iPhone 4 to the limits with 6 or 7 layers at a time all with radically different settings ranging from lifespan to color to spin. </p>
<p>It has everything you&#8217;d expect from a particle emitter. You can email yourself a plist for your newly created particle or use iTunes file sharing to download it to your computer. I didn&#8217;t try it but I&#8217;m sure using your created particle in CAParticleEmitter or Cocos2d would be a breeze. So get out there and start making particle systems on the go!</p>
<ul>
<li><em>Author:</em> <a href="http://www.mutantskin.com/">Tertius Steyn</a> </li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/6063/uikit-particle-systems-in-ios-5-tutorial">UIKit Particle Systems in iOS 5</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fparticulate%252Fid516550478%253Fls%253D1%2526mt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Blow Out Monsters</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/blowoutmonsters" rel="attachment wp-att-13586"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/blowoutmonsters-250x166.jpg" alt="" title="blowoutmonsters" width="250" height="166" class="alignright size-thumbnail wp-image-13586 photo" /></a>Blow Out Monsters is a great action/strategy game. You control a space ship with a powerful laser cutting through space. Your goal is to divide and conquer all the monsters, by cutting pieces of the board out so the monsters are trapped outside.</p>
<p>The twist is you can turn on and off your laser but when you turn it on you lose your shield and are vulnerable to the monsters attacks.   This makes for a really fun game that requires good timing, and better strategy!</p>
<ul>
<li><em>Author:</em> <a href="http://www.alizinhouse.com/">Ibrahim ALIZ</a> <a href="http://twitter.com/ibrahimaliz">@ibrahimaliz</a></li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/692/rotating-turrets">Rotating Turrets: How To Make A Simple iPhone Game with Cocos2D Part 2</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Ftr%252Fapp%252Fblow-out-monsters%252Fid507811484%253Fmt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Color Pad for iPad</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/photo-1" rel="attachment wp-att-13593"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/photo-1-187x250.png" alt="" title="photo 1" width="187" height="250" class="alignright size-thumbnail wp-image-13593 photo" /></a>Color Pad is a freestyle drawing application with a clean and fun interface that gives you everything you need to make art.</p>
<p>How great that art is will depend on you :]</p>
<p>You can pull in pictures from your iPad&#8217;s photo library to give your picture a realistic background. Once you finish you can save it off to your iPad Photo Library or share it with friends through email and Facebook. </p>
<p>Color Pad for iPad is one of the simplest drawing apps I&#8217;ve seen. It gets all the interface distractions out of the way so you can just draw. Great for kids or overzealous adults who like to touch every button :)</p>
<p>Good news: Abdul threw in an extra promo for you guys! Grab it quick: YP3P6M4KRPEL.  If you snag the code, please draw Abdul a thank you and post it to the comments :) Happy Coloring!</p>
<ul>
<li><em>Author:</em> <a href="http://www.datainvent.com">Abdul Azeem Khan</a> <a href="http://twitter.com/Abdul_azeem">@Abdul_azeem</a></li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/1797/how-to-create-a-simple-iphone-app-tutorial-part-1">How To Create a Simple iPhone App on iOS 5 Tutorial: 1/3</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fcolor-pad%252Fid521411414%253Fls%253D1%2526mt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Gravity Pop</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/gravitypop" rel="attachment wp-att-13590"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/gravitypop-250x166.jpg" alt="" title="gravitypop" width="250" height="166" class="alignright size-thumbnail wp-image-13590 photo" /></a>Gravity Pop is an ultra addicting puzzle game where you control gravity itself! </p>
<p>Simple swipes on the screen change the gravity of the game board. Use your new found power over gravity to tip the scales in your favor as you try to pop groups of colored bubbles. </p>
<p>With three exciting game types, three bonus power ups, and global high scores you won&#8217;t be bored anytime soon. </p>
<p>Beware, power over gravity is addicting and will ruin other games for you as you try to cheat with simple swipes in other games. I tried to swipe the gravity in Angry Birds but it didn&#8217;t work :[   +1 Gravity Pop! Angry Birds 0.</p>
<p>Good news: Jonathan was kind enough to throw in some promos for you guys too!  M7MXY9A9NHN4,734K3JYE6EN3,3PNRH46RHFFR,WY4N9R9KNKE3</p>
<ul>
<li><em>Author:</em> <a href="http://gravitypop.thedewpoint.com/">Jonathan Sibley</a> <a href="http://twitter.com/jonsibley">@jonsibley</a></li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/5480/beginning-turn-based-gaming-with-ios-5-part-1">Beginning Turn-Based Gaming with iOS 5</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fgravity-pop%252Fid507329628%253Fls%253D1%2526mt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Video+</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/videoplus" rel="attachment wp-att-13598"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/videoplus-173x250.jpg" alt="" title="videoplus" width="173" height="250" class="alignright size-thumbnail wp-image-13598 photo" /></a>Video+ is a great app for recording video with effects. Some really really cool effects. Its like Camera+ for Video. Imagine that haha! </p>
<p>I didn't count the effects but I'd bet theres over 30. And each effect has a full range of settings to adjust it. Some can be edited so far it's almost a completely different effect. </p>
<p>After you've recorded your video it's saved to your Camera Roll so you can do whatever you like with it. Including AirPlay out to your Apple TV. Definitely worth checking this one out.</p>
<ul>
<li><em>Author:</em> <a href="http://www.videoplusapp.com">Dawid Patek</a> </li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/3664/opengl-es-2-0-for-iphone-tutorial">OpenGL ES 2.0 for iPhone Tutorial</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fvideo%252B-realtime-video-effects%252Fid519874369%253FpartnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Missing Melody</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/missingmelody" rel="attachment wp-att-13591"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/missingmelody-250x187.png" alt="" title="missingmelody" width="250" height="187" class="alignright size-thumbnail wp-image-13591 photo" /></a>Do you more the death of CD's? Vinyls even? Do you love and miss the good old days of 8bit soundtracks? Then this game is for you! </p>
<p>In this game, your goal is to save the dying record industry.  To do this, you transform into one of three characters and embark on a quest to retrieve all the lost CDs and records. But watch out for brick walls, snowcats, and giant pits in the ground!</p>
<p>Missing Melody has some awesome music. And a very cool controller system allowing you to pick between good old buttons, hidden touch zones, or simple swipe based controls. </p>
<p>Don't let the record music industry down!</p>
<ul>
<li><em>Author:</em> <a href="https://sites.google.com/site/myice92ios/">Apikrit Panichevaluk</a> <a href="http://twitter.com/myice92ios">@myice92ios</a></li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial">How To Make A Simple iPhone Game with Cocos2D Tutorial<br />
</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fmissing-melody%252Fid511943307%253FpartnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Gemstone Challenge</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/gemstonechallenge" rel="attachment wp-att-13589"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/gemstonechallenge-166x250.jpg" alt="" title="gemstonechallenge" width="166" height="250" class="alignright size-thumbnail wp-image-13589 photo" /></a>Gemstone challenge is a super addicting puzzle game based on matching gem blocks by color and shape. It has single player classic, timed modes, and online multiplayer through GameCenter. </p>
<p>If you're like me, then it won't take long to find the gems closing in on you. Thats where the multicolor super bombs come in to save the day and blast away entire rows at a time! </p>
<p>Brag about your high scores in the comments all you want (but don't expect to beat my 98,300)!</p>
<p>Good news: Julien was nice enough to give me an extra copy to pass along to you guys. Grab it quick! YLW76JNFEN44</p>
<ul>
<li><em>Author:</em> <a href="http://jw.gaming.free.fr/">Julien Wyart</a> </li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/3276/how-to-make-a-simple-multiplayer-game-with-game-center-tutorial-part-12">How To Make A Simple Multiplayer Game with Game Center</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fgemstone-challenge%252Fid448918316%253Fmt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Flip the Bird</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/flipthebird" rel="attachment wp-att-13588"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/flipthebird-250x187.png" alt="" title="flipthebird" width="250" height="187" class="alignright size-thumbnail wp-image-13588 photo" /></a>Flip the bird is a very special bird. His hunger knows no bounds.  So much so that he devoured his own siblings!  </p>
<p>Understandably, that made his parents kinda mad so the kicked him out of the nest.  Your goal is to help him survive in the scary world outside, by dodging deadly bees and rocks. </p>
<p>Try to hitch a ride on a runaway crow or high strung squirrel. Use unsuspecting birds and mushrooms as boosts while you bounce and flap along. </p>
<p>You've never met a bird quite like Flip!</p>
<ul>
<li><em>Author:</em> <a href="http://codeworxstudios.com">Hunter Mayer</a> <a href="http://twitter.com/FlipTheBirdGame">@FlipTheBirdGame</a></li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/2361/how-to-create-and-optimize-sprite-sheets-in-cocos2d-with-texture-packer-and-pixel-formats">How to Create and Optimize Sprite Sheets in Cocos2d with Texture Packer and Pixel Formats</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fflip-the-bird%252Fid452552250%253Fmt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Quadrobounce</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/quadrobounce" rel="attachment wp-att-13595"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/quadrobounce-166x250.jpg" alt="" title="quadrobounce" width="166" height="250" class="alignright size-thumbnail wp-image-13595 photo" /></a>Quadrobounce is single player pong on steroids, where you control four separate paddles using your iPhones accelerometer. </p>
<p>Did I mention there were four paddles? How about that they move around simultaneously exactly based on your tilt? Ok cool.  ;]</p>
<p>This game is super simple to pick up and play but it definitely takes practice to master. GameCenter integration brings it all together. Quadrobounce!</p>
<ul>
<li><em>Author:</em> <a href="http://suaveapps.tumblr.com">Jonathan Hirz</a> <a href="http://twitter.com/jonnysuave">@jonnysuave</a></li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial">How To Make A Simple iPhone Game with Cocos2D</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fquadrobounce!%252Fid456018898%253Fls%253D1%2526mt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>RPS Mutants</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/rpsmutants" rel="attachment wp-att-13596"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/rpsmutants-166x250.jpg" alt="" title="rpsmutants" width="166" height="250" class="alignright size-thumbnail wp-image-13596" /></a>RPS Mutants is fresh take on a good old favorite. Its rock, paper, scissors like you&#8217;ve never seen it before.   In fact, its the cutest, most addicting rock, paper, scissors variation I&#8217;ve ever seen! </p>
<p>Rocks, pieces of paper, and you guessed it, pairs of scissors rain from the sky for some strange reason. You&#8217;re randomly assigned an item and you&#8217;ve got to stay clear of enemies that can hurt you and copies while trying to snag as many victories against the weak enemies as you can. </p>
<p>But beware or dangerous, shape-shifting, lightning that will mutate you into another RPS artifact and throw you off your game. Keep an eye out for powerups too like invincible shields and turboboosts.</p>
<ul>
<li><em>Author:</em> <a href="http://www.kentoh.com">Ken Toh</a> <a href="http://twitter.com/ken_toh">@ken_toh</a></li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial">How to make a simple iPhone game with Cocos2d</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Frps-mutants%252Fid511688118%253Fmt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Pool Chalkboard</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/poolchalkboard"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/poolchalkboard-166x250.png" alt="" title="poolchalkboard" width="166" height="250" class="alignright size-thumbnail wp-image-13597 photo" /></a>Pool Chalkboard will help you take your Pool to the next level. </p>
<p>You can use it to plan out your next shot with painstaking precision. Or you can show off that really cool trick shot you did down at the pub. Or if you&#8217;re like me and can&#8217;t play pool to save your life, you can show everyone what you were actually aiming for. :p  </p>
<p>However you use it, Pool Chalkboard will make a great addition to any complex pool master conversation.</p>
<ul>
<li><em>Author:</em> <a href="http://www.dancesofdragons.com/">Robert Orich</a></li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/8003/how-to-submit-your-app-to-apple-from-no-account-to-app-store-part-1">How to submit your app to Apple from no account to App Store Part 1</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fpool-chalkboard%252Fid505903443%253Fmt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>WordJams</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/wodjams" rel="attachment wp-att-13599"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/wodjams-166x250.png" alt="" title="wodjams" width="166" height="250" class="alignright size-thumbnail wp-image-13599 photo" /></a>Word Jams is a fresh take on word games. </p>
<p>After picking your difficulty (Hard Crust if you&#8217;re a man!) you&#8217;re given a fresh batch of toast to jam. One at a time you are given letters to place on your toast board. The goal is to try and lay them out to create as many words as possible. </p>
<p>After you&#8217;ve laid all your jam it will score your toast and determine how many words you made. Swiping will show you words made and tapping the words will show you their definition. Definitely original, definitely fun!</p>
<ul>
<li><em>Author:</em> <a href="www.amalgamerger.com">Patrick Smith</a> </li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial">How to Save Your App Data with NSCoding and NSFileManager</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fwordjams%252Fid513342703%253Fmt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Picross HD</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/picross" rel="attachment wp-att-13594"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/picross-250x166.jpg" alt="" title="picross" width="250" height="166" class="alignright size-thumbnail wp-image-13594 photo" /></a>Picross is a fun puzzle game that give you numerical clues to help solve a pixel grid design. </p>
<p>It&#8217;s a very addicting game, with  tons of puzzles to keep you going.  If you manage to run out, there are several puzzle packs to buy in the app &#8211; including an Unlimited Daily puzzle upgrade for you hardcore Picrossers!</p>
<p>Good news: Tod was nice enough to give me some extra promo codes for you guys! Get them while they&#8217;re hot! Y3PRN9FRYW3T, JWNF39Y6W7AP, NXW737MWJ336</p>
<ul>
<li><em>Author:</em> <a href="http://fivelakesstudio.com">Tod Cunningham</a> <a href="http://twitter.com/fivelakesstudio">@fivelakesstudio</a></li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/2876/how-to-localize-an-iphone-app-tutorial">How To Localize an iPhone App Tutorial</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fpicross-hd-pixel-puzzles%252Fid381551512%253Fmt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<h2>Zip Zap</h2>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/zipzap" rel="attachment wp-att-13600"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/05/zipzap-250x187.jpg" alt="" title="zipzap" width="250" height="187" class="alignright size-thumbnail wp-image-13600 photo" /></a>Zip Zap is a killer 3D space game. Asteroids are all over the place crashing into your ship. Its up to you to blow them up with your power shield. </p>
<p>Tap where you want to go and blow up all the asteroids along your path. As you beat back the asteroids more will come. If you&#8217;re really good you&#8217;ll get more ground to cover. Powerups will help you along the way. Its super addicting once you get started. </p>
<p>Defend your ship at all costs! Oh, by the way, I made it to 338,807! Beat that!</p>
<ul>
<li><em>Author:</em> <a href="http://industrycorp.ca">Rani Lian</a> </li>
<li><em>Most useful tutorial</em>: <a href="http://www.raywenderlich.com/1371/how-to-integrate-iad-into-your-iphone-app">How to Integrate iAd into your iPhone App</a></li>
<li><em>App Store Link:</em> <a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fca%252Fapp%252Fzip-zap%252Fid517358765%253Fmt%253D8%2526partnerId%253D30">Check it out!</a></li>
</ul>
<p></p>
<p></br></br></p>
<h2> Honorable Mentions</h2>
<p>Here are the apps that didn&#8217;t get reviewed. Remember it wasn&#8217;t a popularity contest or even a rating contest. Forum members got priority among other factors. Your apps were great and I&#8217;m sorry we didn&#8217;t have time to review them all!</p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Ffeed-browser%252Fid509920956%253Fls%253D1%2526mt%253D8%2526partnerId%253D30" target="itunes_store">Feed Browser</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fau%252Fapp%252Fworktime-radar%252Fid521463667%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">Worktime Radar</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fawesome-cowbell%252Fid501243261%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">Awesome Cowbell</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fmonster-mayhem-apocalypse%252Fid511751881%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">Monster Mayhem Apocalypse</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fpicky-fruit%252Fid508543850%253FpartnerId%253D30" target="itunes_store">Picky Fruit</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fibehave%252Fid495667452%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">iBehave</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fdream-guy%252Fid512441628%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">Dream Guy</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fapp%252Fid318894849%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">Period Plus</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Flinsanity-rush%252Fid514803088%253Fls%253D1%2526mt%253D8%2526partnerId%253D30" target="itunes_store">Linsanity Rush</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fisaleprice%252Fid517538915%253Fls%253D1%2526mt%253D8%2526partnerId%253D30" target="itunes_store">iSalePrice</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Freddit-photo-clock-hd%252Fid498454187%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">Reddit Photo Clock</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fqi-iq-learn-two-letter-words%252Fid513376129%253Fls%253D1%2526mt%253D8%2526partnerId%253D30" target="itunes_store">Qi iQ &#8211; Learn Two letter Words</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fbaby-shaper%252Fid514053322%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">Baby Shaper</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fapp%252Fballsbreaker%252Fid486171368%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">BallsBreaker</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fdilemmas%252Fid505953736%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">Dilemmas</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fmy-kids-health%252Fid483524736%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">My Kids Health</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fwhere2boss%252Fid496587926%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">Where2Boss</a></p>
<p><a href="http://click.linksynergy.com/fs-bin/stat?id=9QfxPcziZp0&#038;offerid=146261&#038;type=3&#038;subid=0&#038;tmpid=1826&#038;RD_PARM1=http%253A%252F%252Fitunes.apple.com%252Fus%252Fapp%252Fworld-of-luck%252Fid489264333%253Fmt%253D8%2526partnerId%253D30" target="itunes_store">World of Luck</a></p>
<h2>Where To Go From Here?</h2>
<p>Thats it for May! Looking forward to the apps you make next month! Since we&#8217;re getting so many responses to better your odds, please make sure you include all the requested information the first time around.</p>
<p>If you are a reader of this site and would like to be considered for this column, shoot an email to <a href="mailto:ryan@raywenderlich.com">ryan@raywenderlich.com</a> with the following info:</p>
<ul>
<li>Your full name and Twitter account if you have one</li>
<li>The name of your app</li>
<li>A promo code for your app (Even if its free)</li>
<li>A link directly to your app in itunes.</li>
<li>The tutorial on the site that was most helpful to development of your app</li>
<li>Your forum account name if you have one (priority given to active forum members)</li>
</ul>
<p>I hope you enjoyed this column, and I look forward to seeing what you guys come up with this month!  :]</p>
<p><img src="http://d1xzuxjlafny7l.cloudfront.net/downloads/RyanPoolos.jpg" class="photo alignleft"/><br />
<i>This is a post by Reader&#8217;s Apps Reviewer <a href="http://www.raywenderlich.com/about#ryanpoolos">Ryan Poolos</a>, an iOS Developer and founder of <a href="http://frozenfirestudios.com">Frozen Fire Studios</a>. Checkout his latest game, <a href="http://PopArcade.net/CL">Cyborg Livestock</a>. Checkout his latest website, <a href="http://www.getihelp.com">iHelp</a>.</i></p>
<p><a href="http://www.raywenderlich.com/13563/readers-app-reviews-may-2012">Readers App Reviews &#8211; May 2012</a> is a post from: <a href="http://www.raywenderlich.com">Ray Wenderlich</a></p>
<div id="tweetbutton13563" class="tw_button" style="float:left;"><a href="http://twitter.com/share?url=http%3A%2F%2Fbit.ly%2FIOyWtQ&amp;via=rwenderlich&amp;text=Readers%20App%20Reviews%20%26%238211%3B%20May%202012&amp;related=EmperiorEric&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fwww.raywenderlich.com%2F13563%2Freaders-app-reviews-may-2012" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://d1xzuxjlafny7l.cloudfront.net/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><img src="http://feeds.feedburner.com/~r/RayWenderlich/~4/JoKKG3AD25A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.raywenderlich.com/13563/readers-app-reviews-may-2012/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.raywenderlich.com/13563/readers-app-reviews-may-2012</feedburner:origLink></item>
		<item>
		<title>iCloud and UIDocument: Beyond the Basics. Part 4/4</title>
		<link>http://feedproxy.google.com/~r/RayWenderlich/~3/A7wELpZV1AA/icloud-and-uidocument-beyond-the-basics-part-4</link>
		<comments>http://www.raywenderlich.com/12837/icloud-and-uidocument-beyond-the-basics-part-4#comments</comments>
		<pubDate>Thu, 10 May 2012 15:00:35 +0000</pubDate>
		<dc:creator>Ray Wenderlich</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iCloud]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[sample code]]></category>
		<category><![CDATA[storyboards]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[UIKit]]></category>

		<guid isPermaLink="false">http://www.raywenderlich.com/?p=12837</guid>
		<description><![CDATA[TweetThis is a blog post by site administrator Ray Wenderlich, an independent software developer and gamer. Welcome back to the [...]<p><a href="http://www.raywenderlich.com/12837/icloud-and-uidocument-beyond-the-basics-part-4">iCloud and UIDocument: Beyond the Basics. Part 4/4</a> is a post from: <a href="http://www.raywenderlich.com">Ray Wenderlich</a></p>
]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton12837" class="tw_button" style="float:left;"><a href="http://twitter.com/share?url=http%3A%2F%2Fbit.ly%2FIwhwXl&amp;via=rwenderlich&amp;text=iCloud%20and%20UIDocument%3A%20Beyond%20the%20Basics.%20Part%204%2F4&amp;related=rwenderlich&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fwww.raywenderlich.com%2F12837%2Ficloud-and-uidocument-beyond-the-basics-part-4" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://d1xzuxjlafny7l.cloudfront.net/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><div id="attachment_12780" class="wp-caption alignright" style="width: 292px"><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/iCloudTutorial.jpg"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/iCloudTutorial-282x320.jpg" alt="Learn how to make a complete UIDocument + iCloud app!" title="Learn how to make a complete UIDocument + iCloud app!" width="282" height="320" class="size-medium wp-image-12780" /></a><p class="wp-caption-text">Learn how to make a complete UIDocument + iCloud app!</p></div>
<p><i>This is a blog post by site administrator <a href="http://www.raywenderlich.com/about">Ray Wenderlich</a>, an independent software developer and gamer.</i></p>
<p>Welcome back to the final part of our document-based iCloud app tutorial series!</p>
<p>In this tutorial series we are making a complete document-based iCloud app called PhotoKeeper, with features that go beyond just the basics.</p>
<p>In the <a href="http://www.raywenderlich.com/12779/icloud-and-uidocument-beyond-the-basics-part-1">first</a> and <a href="http://www.raywenderlich.com/12794/icloud-and-uidocument-beyond-the-basics-part-2">second</a> part of the series, we made a fully functional UIDocument-based app that works with local files with full CRUD support.</p>
<p>In this <a href="http://www.raywenderlich.com/12816/icloud-and-uidocument-beyond-the-basics-part-3">third</a> part of the series, we got iCloud mostly working.  All CRUD operations are functional, and you can even rename and delete files.</p>
<p>That brings us to this fourth and final part of the series!  Here we&#8217;ll show you how you can resolve conflicts, and move/copy files to/from iCloud.</p>
<p>This project continues where we left off last time, so if you don&#8217;t have it already grab the previous <a href="http://d1xzuxjlafny7l.cloudfront.net/downloads/PhotoKeeper3.zip">code sample</a> and open up the project.  Let&#8217;s wrap this project up!<span id="more-12837"></span><br />
<h2>iCloud and Conflicts: Overview</h2>
<p>Open your project and open the same document on two different devices.  Change the picture on both at the same time, tap Done, and see what happens.</p>
<p>Basically iCloud will automatically choose the &#8220;lastest change&#8221; as the current document by default.  But since this is dependent on network connections, this might not be what the user actually wants.</p>
<p>The good news is when the same document is modified at the same time like this, iCloud will detect this as a conflict and store copies of any conflicting documents.  It&#8217;s up to you how you deal with the conflict &#8211; you could try to merge changes or let the user pick one (or more) of the versions to keep.</p>
<p>In this tutorial, when there&#8217;s a conflict we&#8217;re going to display a view controller to the user that shows the conflicts and allows the user to pick one of them to keep.  You might want to use a slightly different strategy for your app, but the same core idea remains.</p>
<h2>Displaying Conflicts</h2>
<p>The first thing we need to do is display and detect conflicts.  UIDocument has a property called documentState that is a bitfield of different flags that can be on a document, including a &#8220;conflict&#8221; state.</p>
<p>We&#8217;ve actually been passing this along in our PTKEntry all along, now&#8217;s our chance to actually use it!</p>
<p>Let&#8217;s start by just logging out what the document state is when we read documents.  Make the following changes to PTKMasterViewController.m:</p>

<div class="wp_codebox"><table><tr id="p1283715"><td class="code" id="p12837code15"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add to top of &quot;Helpers&quot; section</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>stringForState<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIDocumentState<span style="color: #002200;">&#41;</span>state <span style="color: #002200;">&#123;</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span> states <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> array<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>state <span style="color: #002200;">==</span> <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>states addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Normal&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>state <span style="color: #002200;">&amp;</span> UIDocumentStateClosed<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>states addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Closed&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>state <span style="color: #002200;">&amp;</span> UIDocumentStateInConflict<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>states addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;In Conflict&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>state <span style="color: #002200;">&amp;</span> UIDocumentStateSavingError<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>states addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Saving error&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>state <span style="color: #002200;">&amp;</span> UIDocumentStateEditingDisabled<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>states addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Editing disabled&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>states componentsJoinedByString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;, &quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Replace &quot;Loaded File URL&quot; log line in loadDocURL with the following</span>
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Loaded File URL: %@, State: %@, Last Modified: %@&quot;</span>, <span style="color: #002200;">&#91;</span>doc.fileURL lastPathComponent<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>self stringForState<span style="color: #002200;">:</span>state<span style="color: #002200;">&#93;</span>, version.modificationDate.mediumString<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>Compile and run your app, and if you have any documents in the conflict state you should see something like this:</p>
<pre class="command">
Loaded File URL: Photo 4.ptk, State: In Conflict, Last Modified: Today 10:01:17 AM
</pre>
<p>Let&#8217;s modify our app to have a visual representation of when a document is in the conflict state.  Open MainStoryboard.storyboard and add a 32&#215;32 image view to the bottom left of the thumbnail image view, and set the image to warning.png:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/AddingWarning.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/AddingWarning-700x255.png" alt="Adding warning image to table view cell" title="Adding warning image to table view cell" width="700" height="255" class="alignnone size-large wp-image-12839" /></a></p>
<p>Then switch to PTKEntryCell.h and add a property for this:</p>
<pre class="objc">
@property (weak, nonatomic) IBOutlet UIImageView * warningImageView;
</pre>
<p>And synthesize it in PTKEntryCell.m:</p>
<pre class="objc">
@synthesize warningImageView;
</pre>
<p>Switch back to MainStoryboard.storyboard, control-drag from the cell to the warning image view, and connect it to the warningImageView outlet.</p>
<p>Finally, open PTKMasterViewController.m and add this to the end of tableView:cellForRowAtIndexPath (before the call to return cell):</p>

<div class="wp_codebox"><table><tr id="p1283716"><td class="code" id="p12837code16"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>entry.state <span style="color: #002200;">&amp;</span> UIDocumentStateInConflict<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    cell.warningImageView.hidden <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
    cell.warningImageView.hidden <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Compile and run, and now if there is a conflict you should see a warning flag next to the document in question!</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/Conflict.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/Conflict.png" alt="Seeing when a UIDocument is in conflict in the table view" title="Seeing when a UIDocument is in conflict in the table view" width="320" height="480" class="alignnone size-full wp-image-12840 bordered" /></a></p>
<h2>Creating a Conflict View Controller</h2>
<p>Now that we know what documents are in conflict, we have to do something about it.  We&#8217;ll create a view controller that lists all the versions that are available and let the user choose one to keep.</p>
<p>Create a new file with the iOS\Cocoa Touch\Objective-C class template, name it PTKConflictViewController, and make it a subclass of UITableViewController.  Make sure the checkboxes are NOT checked, and finish creating the file.</p>
<p>We&#8217;ll add the code for this later, first let&#8217;s design the UI.  Open MainStoryboard.storyboard, and drag a new UITableViewController into the storyboard below the detail view controller.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/AddingTableViewController.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/AddingTableViewController.png" alt="Adding a new table view controller to the Storyboard editor" title="Adding a new table view controller to the Storyboard editor" width="394" height="321" class="alignnone size-full wp-image-12841" /></a></p>
<p>We want the master view controller to display it, so control-drag from the master view controller to the new table view controller, and choose Push from the popup.  Then click the segue and name it &#8220;showConflicts&#8221;:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/AddingConflictsSegue.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/AddingConflictsSegue-700x288.png" alt="Adding a new segue to display the conflicts view controller" title="Adding a new segue to display the conflicts view controller" width="700" height="288" class="alignnone size-large wp-image-12842" /></a></p>
<p>Next zoom in to 100% size and let&#8217;s set up the table view cell.  Set the row height to 80, and add an image view and two labels roughly like the following:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/TableViewCellLayout.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/TableViewCellLayout.png" alt="Laying out a table view cell for conflicts" title="Laying out a table view cell for conflicts" width="640" height="311" class="alignnone size-full wp-image-12843" /></a></p>
<p>We could create a custom cell sublass like we did before for the master table view, but I&#8217;m feeling lazy so we&#8217;ll look up the subviews by tag instead.  So set  the tag of the image view to 1, the first label to 2, and the second label to 3.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingTag.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingTag-700x266.png" alt="Setting the tag on a view in the Storyboard editor" title="Setting the tag on a view in the Storyboard editor" width="700" height="266" class="alignnone size-large wp-image-12844" /></a></p>
<p>To finish configuring the cell we need to set a cell reuse identifier for our cell so we can dequeue it.  Select the Table View Cell and set the Identifeir to MyCell.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingCellIdentifier.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingCellIdentifier-700x276.png" alt="Setting the conflict cell&#039;s identifier" title="Setting the conflict cell&#039;s identifier" width="700" height="276" class="alignnone size-large wp-image-12845" /></a></p>
<p>Finally, we need to set the class of our view controller.  Select the table View Controller and in the identity inspector set the cass to PTKConflictViewController.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingViewControllerClass.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingViewControllerClass-700x270.png" alt="Setting the view controller class in the Identity inspector" title="Setting the view controller class in the Identity inspector" width="700" height="270" class="alignnone size-large wp-image-12846" /></a></p>
<p>Before we implement the PTKConflictViewController, we should create a class to keep track of everything we need to know for each cell (similar to PTKEntry).  </p>
<p>For a conflicted file, you can get a list of all of the different versions of the file that are in conflict.  These versions are referenced via the NSFileVersion class. </p>
<p>So we need to keep track of the NSFileVersion for each row, open that version and get its metadata as well (so we can display the thumbnail to the user).</p>
<p>Create a new file with the iOS\Cocoa Touch\Objective-C class template, name it PTKConflictEntry, and make it a subclass of NSObject.  Then replace the contents of PTKConflictEntry.h with the following:</p>

<div class="wp_codebox"><table><tr id="p1283717"><td class="code" id="p12837code17"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;Foundation/Foundation.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@class</span> PTKMetadata;
&nbsp;
<span style="color: #a61390;">@interface</span> PTKConflictEntry <span style="color: #002200;">:</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a>
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong<span style="color: #002200;">&#41;</span> NSFileVersion <span style="color: #002200;">*</span> version;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong<span style="color: #002200;">&#41;</span> PTKMetadata <span style="color: #002200;">*</span> metadata;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithFileVersion<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSFileVersion <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>version metadata<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>PTKMetadata <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>metadata;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>And replace PTKConflictEntry.m with the following:</p>

<div class="wp_codebox"><table><tr id="p1283718"><td class="code" id="p12837code18"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;PTKConflictEntry.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> PTKConflictEntry
<span style="color: #a61390;">@synthesize</span> version <span style="color: #002200;">=</span> _version;
<span style="color: #a61390;">@synthesize</span> metadata <span style="color: #002200;">=</span> _metadata;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithFileVersion<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSFileVersion <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>version metadata<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>PTKMetadata <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>metadata <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        self.version <span style="color: #002200;">=</span> version;
        self.metadata <span style="color: #002200;">=</span> metadata;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Finally onwards to implementing PTKConflictViewController!  When displaying the view controller, we&#8217;ll pass in the fileURL to display conflicts for, so modify PTKConflictViewController.h to the following:</p>

<div class="wp_codebox"><table><tr id="p1283719"><td class="code" id="p12837code19"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;UIKit/UIKit.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> PTKConflictViewController <span style="color: #002200;">:</span> UITableViewController
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong<span style="color: #002200;">&#41;</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> fileURL;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Then make the following changes to PTKConflictViewController.m:</p>

<div class="wp_codebox"><table><tr id="p1283720"><td class="code" id="p12837code20"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add imports to the top of the file</span>
<span style="color: #6e371a;">#import &quot;PTKConflictEntry.h&quot;</span>
<span style="color: #6e371a;">#import &quot;PTKDocument.h&quot;</span>
<span style="color: #6e371a;">#import &quot;PTKMetadata.h&quot;</span>
<span style="color: #6e371a;">#import &quot;NSDate+FormattedStrings.h&quot;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Modify @implementation to add a private instance variable for the entries and synthesize fileURL</span>
<span style="color: #a61390;">@implementation</span> PTKConflictViewController <span style="color: #002200;">&#123;</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span> _entries;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">@synthesize</span> fileURL;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add to end of viewDidLoad</span>
_entries <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> array<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Replace numberOfSectionsInTableView, numberOfRowsInSection, and cellForRowAtIndexPath with the following</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>numberOfSectionsInTableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #2400d9;">1</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView numberOfRowsInSection<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>section
<span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%d rows&quot;</span>, _entries.count<span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">return</span> _entries.count;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>UITableViewCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView cellForRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">static</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>CellIdentifier <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;MyCell&quot;</span>;
    UITableViewCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>tableView dequeueReusableCellWithIdentifier<span style="color: #002200;">:</span>CellIdentifier<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Configure the cell...</span>
    UIImageView <span style="color: #002200;">*</span> imageView <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>UIImageView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#91;</span>cell viewWithTag<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span>;
    UILabel <span style="color: #002200;">*</span> titleLabel <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>UILabel <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#91;</span>cell viewWithTag<span style="color: #002200;">:</span><span style="color: #2400d9;">2</span><span style="color: #002200;">&#93;</span>;
    UILabel <span style="color: #002200;">*</span> subtitleLabel <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>UILabel <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#91;</span>cell viewWithTag<span style="color: #002200;">:</span><span style="color: #2400d9;">3</span><span style="color: #002200;">&#93;</span>;
    PTKConflictEntry <span style="color: #002200;">*</span> entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_entries objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>entry.metadata<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        imageView.image <span style="color: #002200;">=</span> entry.metadata.thumbnail;
    <span style="color: #002200;">&#125;</span>
    titleLabel.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Modified on %@&quot;</span>, entry.version.localizedNameOfSavingComputer<span style="color: #002200;">&#93;</span>;
    subtitleLabel.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>entry.version.modificationDate mediumString<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> cell;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>OK so that&#8217;s pretty straightforward &#8211; we&#8217;re just displaying any PTKConflictEntry classes in the _entries array.</p>
<p>But what about creating these PTKConflictEntry classes in the first place from the fileURL?  We&#8217;ll do that in viewWillAppear.  Add this right after viewDidUnload:</p>

<div class="wp_codebox"><table><tr id="p1283721"><td class="code" id="p12837code21"><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>viewWillAppear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>_entries removeAllObjects<span style="color: #002200;">&#93;</span>;    
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span> fileVersions <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> array<span style="color: #002200;">&#93;</span>;
&nbsp;
    NSFileVersion <span style="color: #002200;">*</span> currentVersion <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSFileVersion currentVersionOfItemAtURL<span style="color: #002200;">:</span>self.fileURL<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>fileVersions addObject<span style="color: #002200;">:</span>currentVersion<span style="color: #002200;">&#93;</span>;
&nbsp;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span> otherVersions <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSFileVersion otherVersionsOfItemAtURL<span style="color: #002200;">:</span>self.fileURL<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>fileVersions addObjectsFromArray<span style="color: #002200;">:</span>otherVersions<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSFileVersion <span style="color: #002200;">*</span> fileVersion <span style="color: #a61390;">in</span> fileVersions<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Create a resolve entry and add to entries</span>
        PTKConflictEntry <span style="color: #002200;">*</span> entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PTKConflictEntry alloc<span style="color: #002200;">&#93;</span> initWithFileVersion<span style="color: #002200;">:</span>fileVersion metadata<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>_entries addObject<span style="color: #002200;">:</span>entry<span style="color: #002200;">&#93;</span>;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span> indexPath <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> indexPathForRow<span style="color: #002200;">:</span>_entries.count<span style="color: #002200;">-</span><span style="color: #2400d9;">1</span> inSection<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Open doc and get metadata - when done, reload row so we can get thumbnail</span>
        PTKDocument <span style="color: #002200;">*</span> doc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PTKDocument alloc<span style="color: #002200;">&#93;</span> initWithFileURL<span style="color: #002200;">:</span>fileVersion.URL<span style="color: #002200;">&#93;</span>;
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Opening URL: %@&quot;</span>, fileVersion.URL<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#91;</span>doc openWithCompletionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
                    entry.metadata <span style="color: #002200;">=</span> doc.metadata;
                    <span style="color: #002200;">&#91;</span>self.tableView reloadRowsAtIndexPaths<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObject<span style="color: #002200;">:</span>indexPath<span style="color: #002200;">&#93;</span> withRowAnimation<span style="color: #002200;">:</span>UITableViewRowAnimationNone<span style="color: #002200;">&#93;</span>;
                <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
                <span style="color: #002200;">&#91;</span>doc closeWithCompletionHandler<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>self.tableView reloadData<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>To get the different versions of the file that are in conflict, you use two different APIs in NSFileVersion &#8211; currentVersionOfItemAtURL (the current &#8220;winning&#8221; version), and otherVersionsOFItemAtURL (the other ones that iCloud isn&#8217;t sure about).  We open up all of these versions and add them to our array, along with their metadata (thumbnail).</p>
<p>Finally, when the user taps a row we want to choose that file version and resolve the conflict.  So replace didSelectRowAtIndexPath at the end of the file with this:</p>

<div class="wp_codebox"><table><tr id="p1283722"><td class="code" id="p12837code22"><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>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView didSelectRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath <span style="color: #002200;">&#123;</span>
&nbsp;
    PTKConflictEntry <span style="color: #002200;">*</span> entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_entries objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>entry.version isEqual<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>NSFileVersion currentVersionOfItemAtURL<span style="color: #002200;">:</span>self.fileURL<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>entry.version replaceItemAtURL<span style="color: #002200;">:</span>self.fileURL options<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;    
    <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#91;</span>NSFileVersion removeOtherVersionsOfItemAtURL<span style="color: #002200;">:</span>self.fileURL error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a><span style="color: #002200;">*</span> conflictVersions <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSFileVersion unresolvedConflictVersionsOfItemAtURL<span style="color: #002200;">:</span>self.fileURL<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSFileVersion<span style="color: #002200;">*</span> fileVersion <span style="color: #a61390;">in</span> conflictVersions<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        fileVersion.resolved <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>self.navigationController popViewControllerAnimated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;    
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>If the user chose one of the &#8220;other&#8221; versions of the file, we replace the current version of the file with what they chose.</p>
<p>We then remove all the other versions, and mark everything as resolved.  Not too hard, eh?</p>
<p>Almost ready to try this out!  Just make the following changes to PTKMasterViewController.m:</p>

<div class="wp_codebox"><table><tr id="p1283723"><td class="code" id="p12837code23"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add new private variable</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> _selURL;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Modify didSelectRowAtIndexPath to check documenet state first</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView didSelectRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath <span style="color: #002200;">&#123;</span>
&nbsp;
    PTKEntry <span style="color: #002200;">*</span> entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_objects objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self.tableView deselectRowAtIndexPath<span style="color: #002200;">:</span>indexPath animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>entry.state <span style="color: #002200;">&amp;</span> UIDocumentStateInConflict<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        _selURL <span style="color: #002200;">=</span> entry.fileURL;
        <span style="color: #002200;">&#91;</span>self performSegueWithIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;showConflicts&quot;</span> sender<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        _selDocument <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PTKDocument alloc<span style="color: #002200;">&#93;</span> initWithFileURL<span style="color: #002200;">:</span>entry.fileURL<span style="color: #002200;">&#93;</span>;    
        <span style="color: #002200;">&#91;</span>_selDocument openWithCompletionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Selected doc with state: %@&quot;</span>, <span style="color: #002200;">&#91;</span>self stringForState<span style="color: #002200;">:</span>_selDocument.documentState<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
                <span style="color: #002200;">&#91;</span>self performSegueWithIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;showDetail&quot;</span> sender<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span> 
&nbsp;
<span style="color: #11740a; font-style: italic;">// Modify prepareForSegue to add a case for the showConflicts segue</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>prepareForSegue<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIStoryboardSegue <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>segue sender<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: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>segue identifier<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;showDetail&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>segue destinationViewController<span style="color: #002200;">&#93;</span> setDelegate<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>segue destinationViewController<span style="color: #002200;">&#93;</span> setDoc<span style="color: #002200;">:</span>_selDocument<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>segue identifier<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;showConflicts&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>segue destinationViewController<span style="color: #002200;">&#93;</span> setFileURL<span style="color: #002200;">:</span>_selURL<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>And that&#8217;s it!  Compile and run, and now when you tap an entry with a conflict you will now see the list of versions in conflict:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/ConflictViewController.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/ConflictViewController.png" alt="The conflict view controller in PhotoKeeper" title="The conflict view controller in PhotoKeeper" width="320" height="480" class="alignnone size-full wp-image-12847 bordered" /></a></p>
<p>And you can tap a file to restore to that verison and resolve the conflict:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/ConflictResolved.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/ConflictResolved.png" alt="A resolved conflict in PhotoKeeper" title="A resolved conflict in PhotoKeeper" width="320" height="480" class="alignnone size-full wp-image-12848 bordered" /></a></p>
<h2>Moving Files To iCloud</h2>
<p>At this point our app is almost done, except for one more bit &#8211; dealing with the user transitioning between iCloud off and iCloud on, and vice versa.  There are two cases:</p>
<ul>
<li><em>local => iCloud.</em> If the user isn&#8217;t using iCloud (and has local files) and starts using iCloud, the app should automatically move all the local files to iCloud (renaming files if necesary to avoid name conflicts).</li>
<li><em>iCloud => local.</em> If the user is using iCloud and wants to turn iCloud off and use local files, we should ask the user what he wants to do.  The options are &#8220;copy the iCloud files to local&#8221;, &#8220;keep files on iCloud&#8221;, or &#8220;switch back to using iCloud.&#8221;</li>
</ul>
<p>Let&#8217;s start with the first case.  We already have the stub for localToiCloud called in the proper situation (we covered this in part 3).  So make the following changes to PTKMasterViewController.m:</p>

<div class="wp_codebox"><table><tr id="p1283724"><td class="code" id="p12837code24"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add a new private instance variable</span>
<span style="color: #a61390;">BOOL</span> _moveLocalToiCloud;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Replace localToiCloud with the following (and add a new method)</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>localToiCloudImpl <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// TODO</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>localToiCloud <span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;local =&gt; iCloud&quot;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// If we have a valid list of iCloud files, proceed</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_iCloudURLsReady<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>self localToiCloudImpl<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> 
    <span style="color: #11740a; font-style: italic;">// Have to wait for list of iCloud files to refresh</span>
    <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        _moveLocalToiCloud <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;         
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add to end of processiCloudFiles, right before enableUpdates</span>
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_moveLocalToiCloud<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>            
    _moveLocalToiCloud <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#91;</span>self localToiCloudImpl<span style="color: #002200;">&#93;</span>;            
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>OK, what&#8217;s going on here?  Well, to move the files to iCloud we need to make sure there are no name conflicts.  But we can&#8217;t know what files are in iCloud until the list of files returns from our NSMetadataQuery.  So if the list of iCloud URLs isn&#8217;t ready, we set a flag to YES.  When the metadata query results come in, we check this flag and call localToiCloudImpl (which will do the actual work) now that we have a valid list of filenames.</p>
<p>Next we need to make a slight tweak to getDocFilename so it can search in the list of iCloudURLs (instead of the list of PTKEntries).  Make the following changes:</p>

<div class="wp_codebox"><table><tr id="p1283725"><td class="code" id="p12837code25"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add right above getDocFilename:uniqueInObjects</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>docNameExistsIniCloudURLs<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>docName <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">BOOL</span> nameExists <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> fileURL <span style="color: #a61390;">in</span> _iCloudURLs<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>fileURL lastPathComponent<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span>docName<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            nameExists <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
            <span style="color: #a61390;">break</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> nameExists;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Replace TODO in docFilename:uniqueInObjects with this</span>
nameExists <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self docNameExistsIniCloudURLs<span style="color: #002200;">:</span>newDocName<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>So by passing in NO to docNameExists:uniqueInObjects we can have it make sure the name is unique in the iCloud URLs (even if iCloud if off).</p>
<p>Next replace localToiCloudImpl with the following:</p>

<div class="wp_codebox"><table><tr id="p1283726"><td class="code" id="p12837code26"><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>localToiCloudImpl <span style="color: #002200;">&#123;</span>
&nbsp;
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;local =&gt; iCloud impl&quot;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span> localDocuments <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> defaultManager<span style="color: #002200;">&#93;</span> contentsOfDirectoryAtURL<span style="color: #002200;">:</span>self.localRoot includingPropertiesForKeys<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> options<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i<span style="color: #002200;">=</span><span style="color: #2400d9;">0</span>; i &lt; localDocuments.count; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> fileURL <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>localDocuments objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</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>fileURL pathExtension<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span>PTK_EXTENSION<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
            <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span> fileName <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>fileURL lastPathComponent<span style="color: #002200;">&#93;</span> stringByDeletingPathExtension<span style="color: #002200;">&#93;</span>;
            <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span>destURL <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self getDocURL<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self getDocFilename<span style="color: #002200;">:</span>fileName uniqueInObjects<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Perform actual move in background thread</span>
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_global_queue<span style="color: #002200;">&#40;</span>DISPATCH_QUEUE_PRIORITY_DEFAULT, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span> error;
                <span style="color: #a61390;">BOOL</span> success <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> defaultManager<span style="color: #002200;">&#93;</span> setUbiquitous<span style="color: #002200;">:</span>self.iCloudOn itemAtURL<span style="color: #002200;">:</span>fileURL destinationURL<span style="color: #002200;">:</span>destURL error<span style="color: #002200;">:&amp;</span>error<span style="color: #002200;">&#93;</span>;
                <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Moved %@ to %@&quot;</span>, fileURL, destURL<span style="color: #002200;">&#41;</span>;
                    <span style="color: #002200;">&#91;</span>self loadDocAtURL<span style="color: #002200;">:</span>destURL<span style="color: #002200;">&#93;</span>;
                <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
                    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Failed to move %@ to %@: %@&quot;</span>, fileURL, destURL, error.localizedDescription<span style="color: #002200;">&#41;</span>; 
                <span style="color: #002200;">&#125;</span>
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>This is the meat of the move logic.  We loop through all of our local files, and get a unique filename for the local filename in iCloud.  We then move the document to iCloud, which you can do by calling the setUbiquitous:itemAtURL:destinationItem method.</p>
<p>Compile and run the app, and make sure iCloud is off.  Create a local document, and turn iCloud back on.  Your local document should move to iCloud!</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/LocalToiCloud.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/LocalToiCloud.png" alt="A local document moved to iCloud in PhotoKeeper" title="A local document moved to iCloud in PhotoKeeper" width="320" height="480" class="alignnone size-full wp-image-12849 bordered" /></a></p>
<h2>Copying Files From iCloud</h2>
<p>Now let&#8217;s try the other way around.  Make the following changes to PTKMasterViewController.m:</p>

<div class="wp_codebox"><table><tr id="p1283727"><td class="code" id="p12837code27"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add new instance variable</span>
<span style="color: #a61390;">BOOL</span> _copyiCloudToLocal;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Replace iCloudToLocal and add a stub</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>iCloudToLocalImpl <span style="color: #002200;">&#123;</span>
&nbsp;
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloud =&gt; local impl&quot;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #11740a; font-style: italic;">// TODO</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>iCloudToLocal <span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloud =&gt; local&quot;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Wait to find out what user wants first</span>
    UIAlertView <span style="color: #002200;">*</span> alertView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;You're Not Using iCloud&quot;</span> message<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;What would you like to do with the documents currently on this iPad?&quot;</span> delegate<span style="color: #002200;">:</span>self cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Continue Using iCloud&quot;</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Keep a Local Copy&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Keep on iCloud Only&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    alertView.tag <span style="color: #002200;">=</span> <span style="color: #2400d9;">2</span>;
    <span style="color: #002200;">&#91;</span>alertView show<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add second case in alertView:didDismissWithButtonIndex</span>
<span style="color: #11740a; font-style: italic;">// @&quot;What would you like to do with the documents currently on this iPad?&quot; </span>
<span style="color: #11740a; font-style: italic;">// Cancel: @&quot;Continue Using iCloud&quot; </span>
<span style="color: #11740a; font-style: italic;">// Other 1: @&quot;Keep a Local Copy&quot;</span>
<span style="color: #11740a; font-style: italic;">// Other 2: @&quot;Keep on iCloud Only&quot;</span>
<span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>alertView.tag <span style="color: #002200;">==</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>buttonIndex <span style="color: #002200;">==</span> alertView.cancelButtonIndex<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #002200;">&#91;</span>self setiCloudOn<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>self refresh<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>buttonIndex <span style="color: #002200;">==</span> alertView.firstOtherButtonIndex<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_iCloudURLsReady<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #002200;">&#91;</span>self iCloudToLocalImpl<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
            _copyiCloudToLocal <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
        <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>buttonIndex <span style="color: #002200;">==</span> alertView.firstOtherButtonIndex <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>            
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Do nothing</span>
&nbsp;
    <span style="color: #002200;">&#125;</span> 
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add to end of processiCloudFiles, right before call to enableUpdates</span>
<span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_copyiCloudToLocal<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    _copyiCloudToLocal <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#91;</span>self iCloudToLocalImpl<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>This follows a similar strategy to what we did before, except we give the user a chance to choose what to do first.</p>
<p>Next replace iCloudToLocalImpl with the following:</p>

<div class="wp_codebox"><table><tr id="p1283728"><td class="code" id="p12837code28"><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>iCloudToLocalImpl <span style="color: #002200;">&#123;</span>
&nbsp;
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloud =&gt; local impl&quot;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> fileURL <span style="color: #a61390;">in</span> _iCloudURLs<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span> fileName <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>fileURL lastPathComponent<span style="color: #002200;">&#93;</span> stringByDeletingPathExtension<span style="color: #002200;">&#93;</span>;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span>destURL <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self getDocURL<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self getDocFilename<span style="color: #002200;">:</span>fileName uniqueInObjects<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Perform copy on background thread</span>
        dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_global_queue<span style="color: #002200;">&#40;</span>DISPATCH_QUEUE_PRIORITY_DEFAULT, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>            
            NSFileCoordinator<span style="color: #002200;">*</span> fileCoordinator <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSFileCoordinator alloc<span style="color: #002200;">&#93;</span> initWithFilePresenter<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#91;</span>fileCoordinator coordinateReadingItemAtURL<span style="color: #002200;">:</span>fileURL options<span style="color: #002200;">:</span>NSFileCoordinatorReadingWithoutChanges error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> byAccessor<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span>newURL<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> <span style="color: #002200;">*</span> fileManager <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
                <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span> error;
                <span style="color: #a61390;">BOOL</span> success <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>fileManager copyItemAtURL<span style="color: #002200;">:</span>fileURL toURL<span style="color: #002200;">:</span>destURL error<span style="color: #002200;">:&amp;</span>error<span style="color: #002200;">&#93;</span>;                     
                <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Copied %@ to %@ (%d)&quot;</span>, fileURL, destURL, self.iCloudOn<span style="color: #002200;">&#41;</span>;
                    <span style="color: #002200;">&#91;</span>self loadDocAtURL<span style="color: #002200;">:</span>destURL<span style="color: #002200;">&#93;</span>;
                <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
                    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Failed to copy %@ to %@: %@&quot;</span>, fileURL, destURL, error.localizedDescription<span style="color: #002200;">&#41;</span>; 
                <span style="color: #002200;">&#125;</span>
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Here we use NSFileManager&#8217;s copyItemAtURL to copy the file, making sure to wrap it in an NSFileCoordinator for safety.</p>
<p>Compile and run the app, and make sure iCloud is enabled.  Then switch to Settings and disable iCloud, and this will appear:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/iCloudSwitchedOffPrompt.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/iCloudSwitchedOffPrompt.png" alt="Prompt when iCloud switched off" title="Prompt when iCloud switched off" width="320" height="480" class="alignnone size-full wp-image-12850 bordered" /></a></p>
<p>If you tap &#8220;Keep a Local Copy&#8221;, you will see the items all copied locally for you!  :]</p>
<h2>Where To Go From Here?</h2>
<p>Here is a download with the state of the <a href="http://d1xzuxjlafny7l.cloudfront.net/downloads/PhotoKeeper4.zip">code sample</a> so far.</p>
<p>Congratulations, you have made a semi-real world document-based iCloud app!  It can do all the basic CRUD operations, as well as the more tricky bits like handling conflicts, handling both local and iCloud documents, and having the capability to switch documents between the two.</p>
<p>I don&#8217;t claim to have done everything in the best possible manner in this tutorial or made no mistakes.  As such, I have put <a href="https://github.com/rwenderlich/PhotoKeeper">this project on GitHub</a> in case anyone wants to take it from here and add any fixes/improvements moving forward.</p>
<p>I hope this tutorial has been useful to anyone trying to get iCloud working with a document-based app.  If you have any questions, comments, or suggestions for improvement, please join the forum discussion below!  :]</p>
<p><img src="http://d1xzuxjlafny7l.cloudfront.net/downloads/RayWenderlich.jpg" class="photo alignleft" /><br />
<i>This is a blog post by site administrator <a href="http://www.raywenderlich.com/about">Ray Wenderlich</a>, an independent software developer and gamer.</i></p>
<p><a href="http://www.raywenderlich.com/12837/icloud-and-uidocument-beyond-the-basics-part-4">iCloud and UIDocument: Beyond the Basics. Part 4/4</a> is a post from: <a href="http://www.raywenderlich.com">Ray Wenderlich</a></p>
<div id="tweetbutton12837" class="tw_button" style="float:left;"><a href="http://twitter.com/share?url=http%3A%2F%2Fbit.ly%2FIwhwXl&amp;via=rwenderlich&amp;text=iCloud%20and%20UIDocument%3A%20Beyond%20the%20Basics.%20Part%204%2F4&amp;related=rwenderlich&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fwww.raywenderlich.com%2F12837%2Ficloud-and-uidocument-beyond-the-basics-part-4" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://d1xzuxjlafny7l.cloudfront.net/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><img src="http://feeds.feedburner.com/~r/RayWenderlich/~4/A7wELpZV1AA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.raywenderlich.com/12837/icloud-and-uidocument-beyond-the-basics-part-4/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.raywenderlich.com/12837/icloud-and-uidocument-beyond-the-basics-part-4</feedburner:origLink></item>
		<item>
		<title>iCloud and UIDocument: Beyond the Basics. Part 3/4</title>
		<link>http://feedproxy.google.com/~r/RayWenderlich/~3/1tWQctUiN0o/icloud-and-uidocument-beyond-the-basics-part-3</link>
		<comments>http://www.raywenderlich.com/12816/icloud-and-uidocument-beyond-the-basics-part-3#comments</comments>
		<pubDate>Wed, 09 May 2012 15:00:23 +0000</pubDate>
		<dc:creator>Ray Wenderlich</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iCloud]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[ios5]]></category>
		<category><![CDATA[sample code]]></category>
		<category><![CDATA[storyboards]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[UIKit]]></category>

		<guid isPermaLink="false">http://www.raywenderlich.com/?p=12816</guid>
		<description><![CDATA[TweetThis is a blog post by site administrator Ray Wenderlich, an independent software developer and gamer. Welcome back to our [...]<p><a href="http://www.raywenderlich.com/12816/icloud-and-uidocument-beyond-the-basics-part-3">iCloud and UIDocument: Beyond the Basics. Part 3/4</a> is a post from: <a href="http://www.raywenderlich.com">Ray Wenderlich</a></p>
]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton12816" class="tw_button" style="float:left;"><a href="http://twitter.com/share?url=http%3A%2F%2Fbit.ly%2FInWTvc&amp;via=rwenderlich&amp;text=iCloud%20and%20UIDocument%3A%20Beyond%20the%20Basics.%20Part%203%2F4&amp;related=rwenderlich&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fwww.raywenderlich.com%2F12816%2Ficloud-and-uidocument-beyond-the-basics-part-3" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://d1xzuxjlafny7l.cloudfront.net/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><div id="attachment_12780" class="wp-caption alignright" style="width: 292px"><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/iCloudTutorial.jpg"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/iCloudTutorial-282x320.jpg" alt="Learn how to make a complete UIDocument + iCloud app!" title="Learn how to make a complete UIDocument + iCloud app!" width="282" height="320" class="size-medium wp-image-12780" /></a><p class="wp-caption-text">Learn how to make a complete UIDocument + iCloud app!</p></div>
<p><i>This is a blog post by site administrator <a href="http://www.raywenderlich.com/about">Ray Wenderlich</a>, an independent software developer and gamer.</i></p>
<p>Welcome back to our document-based iCloud app tutorial series!</p>
<p>In this tutorial series we are making a complete document-based iCloud app called PhotoKeeper, with features that go beyond just the basics.</p>
<p>In the <a href="http://www.raywenderlich.com/12779/icloud-and-uidocument-beyond-the-basics-part-1">first</a> and <a href="http://www.raywenderlich.com/12794/icloud-and-uidocument-beyond-the-basics-part-2">second</a> part of the series, we made a fully functional UIDocument-based app that works with local files with full CRUD support.</p>
<p>In this third part of the series, it&#8217;s finally time to dive into iCloud!  We will get almost everything working on iCloud in this tutorial, except for some subtle bits which we&#8217;ll leave for the final part of the series.</p>
<p>This project continues where we left off last time, so if you don&#8217;t have it already grab the previous <a href="http://d1xzuxjlafny7l.cloudfront.net/downloads/PhotoKeeper2.zip">code sample</a> and open up the project.  It&#8217;s iCloud time, baby!<span id="more-12816"></span></p>
<h2>Checking if iCloud is Available</h2>
<p>Before you can use iCloud, you first need to check if it is available by calling NSFileManager&#8217;s URLForUbiquityContainerIdentifier method.  </p>
<p>This method also initializes iCloud for you, and returns the URL of the &#8220;iCloud directory&#8221;  &#8211; that is, the directory that that the iCloud daemon checks for files to sychronize to the cloud.</p>
<p>This call might block so it&#8217;s important to call it from a background thread.  Let&#8217;s try it out.  Open PTKMasterViewController.m and make the following changes:</p>

<div class="wp_codebox"><table><tr id="p1281643"><td class="code" id="p12816code43"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add new private instance variable</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> _iCloudRoot;
<span style="color: #a61390;">BOOL</span> _iCloudAvailable;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add to end of &quot;Helpers&quot; section</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>initializeiCloudAccessWithCompletion<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> available<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> completion <span style="color: #002200;">&#123;</span>
    dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_global_queue<span style="color: #002200;">&#40;</span>DISPATCH_QUEUE_PRIORITY_DEFAULT, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
        _iCloudRoot <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> defaultManager<span style="color: #002200;">&#93;</span> URLForUbiquityContainerIdentifier<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_iCloudRoot <span style="color: #002200;">!=</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
                NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloud available at: %@&quot;</span>, _iCloudRoot<span style="color: #002200;">&#41;</span>;
                completion<span style="color: #002200;">&#40;</span>TRUE<span style="color: #002200;">&#41;</span>;
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;            
        <span style="color: #002200;">&#125;</span>            
        <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
                NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloud not available&quot;</span><span style="color: #002200;">&#41;</span>;
                completion<span style="color: #002200;">&#40;</span>FALSE<span style="color: #002200;">&#41;</span>;
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>The most important part here is that we call URLForUbiquityContainerIdentifier to figure out where the iCloud root directory is.  If it returns nil, that means iCloud isn&#8217;t available.</p>
<p>Notice we take a block as a parameter &#8211; it&#8217;s a method we&#8217;ll call after URLForUbiquityContainerIdentifier completes to  indicate whether or not iCloud is available.  If you&#8217;re a bit rusty on blocks, you might want to check out our <a href="http://www.raywenderlich.com/9328/creating-a-diner-app-using-blocks-part-1">blocks tutorial</a>.</p>
<p>Now let&#8217;s try this out.  Go to the refresh method and replace it with the following:</p>

<div class="wp_codebox"><table><tr id="p1281644"><td class="code" id="p12816code44"><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>refresh <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>_objects removeAllObjects<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self.tableView reloadData<span style="color: #002200;">&#93;</span>;
&nbsp;
    self.navigationItem.rightBarButtonItem.enabled <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#91;</span>self initializeiCloudAccessWithCompletion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> available<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        _iCloudAvailable <span style="color: #002200;">=</span> available;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// TODO</span>
&nbsp;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>self iCloudOn<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #002200;">&#91;</span>self loadLocal<span style="color: #002200;">&#93;</span>;        
        <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>The only difference here is we wait until we check if iCloud is available before refreshing our list of files.</p>
<p>Compile and run the app on your device &#8211; not the simulator, because iCloud doesn&#8217;t work on the simulator.  You should see this in the console:</p>
<pre class="command">
iCloud not available
</pre>
<p>You should see this whether you have iCloud enabled or not in Settings.  What gives?</p>
<p>This is because for your app to use iCloud, you have to do several project configuration steps.  Let&#8217;s get to it!</p>
<h2>Configuring your Project for iCloud</h2>
<p>The first step is to visit the <a href="https://developer.apple.com/devcenter/ios/index.action">iOS Developer Center</a> and go to the iOS Provisioning Portal.  Click App IDs in the sidebar and then New App ID.  Create an App ID for your app, similar to the following:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/1-CreateAppID.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/1-CreateAppID-700x469.png" alt="Creating an App ID" title="Creating an App ID" width="700" height="469" class="size-large wp-image-12818" /></a></p>
<p>After you are done, you will see your App ID in the list:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/2-ConfigureAppID.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/2-ConfigureAppID-700x38.png" alt="Configuring an App ID for iCloud" title="Configuring an App ID for iCloud" width="700" height="38" class="size-large wp-image-12819" /></a></p>
<p>Note that iCloud is not enabled by default &#8211; you have to configure it.  To do so, simply click the Configure button, check the checkbox for Enable for iCloud, and click Done.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/3-EnableForiCloud.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/3-EnableForiCloud-700x393.png" alt="Enabling an App ID for iCloud" title="Enabling an App ID for iCloud" width="700" height="393" class="size-large wp-image-12820" /></a></p>
<p>Next you need to create a provisioning profile for your App ID.  Click the Provisioning tab, click New Profile, and select the appropriate information like you can see below.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/4-CreateProvProfile.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/4-CreateProvProfile-700x310.png" alt="Creating a Provisioning Profile" title="Creating a Provisioning Profile" width="700" height="310" class="size-large wp-image-12821" /></a></p>
<p>After you finish creating the profile, refresh the page until it is available for download, and download it.  Double click it to install it in Xcode.  You should see it in the Organizer when you&#8217;re done:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/5-DownloadProvProfile.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/5-DownloadProvProfile-700x106.png" alt="Viewing a Provisioning Profile in Organizer" title="Viewing a Provisioning Profile in Organizer" width="700" height="106" class="size-large wp-image-12822" /></a></p>
<p>Next, you need to set up your Xcode project to use this provisioning profile.  Click your project in the Project Navigator, select the PhotoKeeper target, adn go to the Build Settings tab.  Search for code sign, and set the code signing identity to your new provisioning profile.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/6-UseProvProfile.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/6-UseProvProfile-700x178.png" alt="Using Provisioning Profile" title="Using Provisioning Profile" width="700" height="178" class="size-large wp-image-12823" /></a></p>
<p>To use iCloud, you need to set up some Entitlements that gives your app access to the iCloud directory.  This used to be a pain but now it&#8217;s extremely simple.  Just go to the Summary tab and click the checkbox for Enable Entitlements.  It should autofill everything else, but sometimes I&#8217;ve seen it not fill out the iCloud Containers section, so you might have to click the plus button and add it if so.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/7-EnableEntitlements.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/7-EnableEntitlements-700x254.png" alt="Enabling iCloud Entitlements" title="Enabling iCloud Entitlements" width="700" height="254" class="alignnone size-large wp-image-12824" /></a></p>
<p>The last step is you need to configure your app to recognize the file types for the documents the app is storing.  This isn&#8217;t absolutely required at this point, but you will run into troubles if you don&#8217;t do it later so you might as well do it now.</p>
<p>Switch to the Info tab and click the plus button in the bottom right.  In the pop-up, select Add Document Type.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/8-AddDocType.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/8-AddDocType.png" alt="Adding a Document Type" title="Adding a Document Type" width="209" height="119" class="alignnone size-full wp-image-12825" /></a></p>
<p>You will see that it has created a new entry for you in the Document Types list above.  Fill it out similarly to this example:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/9-ConfigureDocType.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/9-ConfigureDocType.png" alt="Configuring a Document Type" title="Configuring a Document Type" width="549" height="278" class="alignnone size-full wp-image-12826" /></a></p>
<p>Next click the plus button again but select Add Exported UTI this time.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/10-AddExportedUTI.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/10-AddExportedUTI.png" alt="Adding an Exported UTI" title="Adding an Exported UTI" width="176" height="118" class="alignnone size-full wp-image-12827" /></a></p>
<p>It will create a new entry for you in the Exported UTIs list above.  Fill it out similarly to this example:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/11-ConfigureUTI.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/11-ConfigureUTI.png" alt="Configuring an Exported UTI" title="Configuring an Exported UTI" width="544" height="239" class="alignnone size-full wp-image-12828" /></a></p>
<p>It is important that whatever you put for Identifier here matches what you put for Types in the Document Types.  Also, I have had trouble with filename extensions that weren&#8217;t exactly 3 characters in length, so if you have any troubles in your app try working with 3 character extensions.</p>
<p>Phew &#8211; finally done!  Compile and run your app, and if all works well you should now see something like this in the console:</p>
<pre class="command">
iCloud available at: file://localhost/private/var/mobile/Library/Mobile%20Documents/
KFCNEC27GU~com~razeware~PhotoKeeper/
</pre>
<p>This gives you the directory on the device where you can find and create iCloud files.  The iCloud daemon will automatically pull down new files to this directory as they become available, update files that are there, watch for changes you put there, etc.</p>
<p>We&#8217;ll use this directory a lot in this tutorial, but before we go we have the first tricky bit about iCloud to discuss &#8211; turning iCloud on and off.</p>
<h2>iCloud On, iCloud Off</h2>
<p>Like we mentioned back in part 1, you shouldn&#8217;t just assume you should use iCloud if it&#8217;s available &#8211; you should allow the user to enable/disable iCloud for your app.</p>
<p>And also like we discussed before, I believe the best place for this configuration option is in Settings (rather than in-app settings).  This way it reduces clutter in your app and discourages users from changing it unnecessarily.</p>
<p>Adding a switch to turn iCloud on and off is easy, so let&#8217;s deal with that first.  Create a new file with the iOS\Resource\Settings Bundle template, and name it Settings.bundle.  Open Settings.bundle\Root.plist, and modify the file to look like the following:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingsBundle.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingsBundle.png" alt="Configuring the Settings.bundle plist to add a switch" title="Configuring the Settings.bundle plist to add a switch" width="604" height="154" class="alignnone size-full wp-image-12829" /></a></p>
<p>Compile and run the app on your device, and switch to the Settings app.  Scroll down to find the category for PhotoKeeper, and you should see a switch for iCloud:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingsSwitch.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingsSwitch.png" alt="iCloud On/Off Switch in Settings" title="iCloud On/Off Switch in Settings" width="320" height="480" class="alignnone size-full wp-image-12830 bordered" /></a></p>
<p>Settings is pretty cool because getting the value for this switch is as easy as reading the &#8220;iCloudOn&#8221; key from NSUserDefaults.</p>
<p>Now that we&#8217;ve got a switch, it starts getting tricky.  We have to make sure we have code that handles all of the following cases:</p>
<ul>
<li>If iCloud isn&#8217;t switched on, but it&#8217;s available (and we haven&#8217;t bugged the user already), ask the user if they want to turn on iCloud.  This way they don&#8217;t necessarily have to go to Settings at all.</li>
<li>If iCloud isn&#8217;t available, but it was on before, warn the user that although the app can&#8217;t access their iCloud files anymore, they&#8217;re still out on the cloud.</li>
<li>If iCloud was switched on (but wasn&#8217;t previously), that means we need to move our local files to iCloud.</li>
<li>If iCloud was switched off (but wasn&#8217;t previously), that means we need to ask the user what to do with the old iCloud files.  The user might want to leave them on iCloud, keep a copy, or change their mind and turn iCloud back on again.</li>
</ul>
<p>To accomplish all this, in addition to the &#8220;iCloudOn&#8221; flag managed by Settings, we need to create two more NSUserDefaults flags &#8211; one for if iCloud &#8220;used to be on&#8221;, and one for if we&#8217;ve prompted the user if they want to use iCloud yet.</p>
<p>Add these wrappers to PTKMasterViewController.m at the top of the &#8220;Helpers&#8221; section (overwriting the old iCloudOn method):</p>

<div class="wp_codebox"><table><tr id="p1281645"><td class="code" id="p12816code45"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>iCloudOn <span style="color: #002200;">&#123;</span>    
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> boolForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloudOn&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: #a61390;">void</span><span style="color: #002200;">&#41;</span>setiCloudOn<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>on <span style="color: #002200;">&#123;</span>    
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> setBool<span style="color: #002200;">:</span>on forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloudOn&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> synchronize<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>iCloudWasOn <span style="color: #002200;">&#123;</span>    
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> boolForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloudWasOn&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: #a61390;">void</span><span style="color: #002200;">&#41;</span>setiCloudWasOn<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>on <span style="color: #002200;">&#123;</span>    
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> setBool<span style="color: #002200;">:</span>on forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloudWasOn&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> synchronize<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>iCloudPrompted <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> boolForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloudPrompted&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: #a61390;">void</span><span style="color: #002200;">&#41;</span>setiCloudPrompted<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>prompted <span style="color: #002200;">&#123;</span>    
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> setBool<span style="color: #002200;">:</span>prompted forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloudPrompted&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/"><span style="color: #400080;">NSUserDefaults</span></a> standardUserDefaults<span style="color: #002200;">&#93;</span> synchronize<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Then make the following changes to PTKMasterViewController.m:</p>

<div class="wp_codebox"><table><tr id="p1281646"><td class="code" id="p12816code46"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add some stub methods to the bottom of the &quot;File management&quot; section</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>iCloudToLocal <span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloud =&gt; local&quot;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>localToiCloud <span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;local =&gt; iCloud&quot;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark iCloud Query</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>startQuery <span style="color: #002200;">&#123;</span>        
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Starting to watch iCloud dir...&quot;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Replace the &quot;TODO&quot; in refresh with the following</span>
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>_iCloudAvailable<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// If iCloud isn't available, set promoted to no (so we can ask them next time it becomes available)</span>
    <span style="color: #002200;">&#91;</span>self setiCloudPrompted<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// If iCloud was toggled on previously, warn user that the docs will be loaded locally</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self iCloudWasOn<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        UIAlertView <span style="color: #002200;">*</span> alertView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;You're Not Using iCloud&quot;</span> message<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Your documents were removed from this iPad but remain stored in iCloud.&quot;</span> delegate<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;OK&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>alertView show<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// No matter what, iCloud isn't available so switch it to off.</span>
    <span style="color: #002200;">&#91;</span>self setiCloudOn<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>; 
    <span style="color: #002200;">&#91;</span>self setiCloudWasOn<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>        
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Ask user if want to turn on iCloud if it's available and we haven't asked already</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>self iCloudOn<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>self iCloudPrompted<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #002200;">&#91;</span>self setiCloudPrompted<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
        UIAlertView <span style="color: #002200;">*</span> alertView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iCloud is Available&quot;</span> message<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Automatically store your documents in the cloud to keep them up-to-date across all your devices and the web.&quot;</span> delegate<span style="color: #002200;">:</span>self cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Later&quot;</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Use iCloud&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        alertView.tag <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
        <span style="color: #002200;">&#91;</span>alertView show<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span> 
&nbsp;
    <span style="color: #11740a; font-style: italic;">// If iCloud newly switched off, move local docs to iCloud</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self iCloudOn<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>self iCloudWasOn<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>                    
        <span style="color: #002200;">&#91;</span>self localToiCloud<span style="color: #002200;">&#93;</span>;                                                           
    <span style="color: #002200;">&#125;</span>                
&nbsp;
    <span style="color: #11740a; font-style: italic;">// If iCloud newly switched on, move iCloud docs to local</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>self iCloudOn<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">&#91;</span>self iCloudWasOn<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>self iCloudToLocal<span style="color: #002200;">&#93;</span>;                    
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Start querying iCloud for files, whether on or off</span>
    <span style="color: #002200;">&#91;</span>self startQuery<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// No matter what, refresh with current value of iCloudOn</span>
    <span style="color: #002200;">&#91;</span>self setiCloudWasOn<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self iCloudOn<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add right after the refresh method</span>
<span style="color: #6e371a;">#pragma mark UIAlertViewDelegate</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>alertView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIAlertView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>alertView didDismissWithButtonIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>buttonIndex <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// @&quot;Automatically store your documents in the cloud to keep them up-to-date across all your devices and the web.&quot;</span>
    <span style="color: #11740a; font-style: italic;">// Cancel: @&quot;Later&quot;</span>
    <span style="color: #11740a; font-style: italic;">// Other: @&quot;Use iCloud&quot;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>alertView.tag <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>buttonIndex <span style="color: #002200;">==</span> alertView.firstOtherButtonIndex<span style="color: #002200;">&#41;</span> 
        <span style="color: #002200;">&#123;</span>
            <span style="color: #002200;">&#91;</span>self setiCloudOn<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;            
            <span style="color: #002200;">&#91;</span>self refresh<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>There&#8217;s a lot of code here, but none of it is very complicated &#8211; it&#8217;s just implementing the logic discussed earlier.  Be sure to read through the refresh method to make sure you understand the basic logic there.</p>
<p>You may wonder why we&#8217;re calling &#8220;startQuery&#8221; even if iCloud is off.  We&#8217;re going to need valid a list of iCloud files for when we implement the iCloudToLocal method.  But don&#8217;t worry, we won&#8217;t display the list if iCloud is off.  More on this later.</p>
<p>There&#8217;s one final step.  Since the user can leave the app and change the value in Settings at any time, we need to refresh whenever the user returns to the app (i.e. the app &#8220;didbecomeactive&#8221;).  So make the following changes to listen for that event:</p>

<div class="wp_codebox"><table><tr id="p1281647"><td class="code" id="p12816code47"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add to the bottom of viewDidLoad</span>
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>didBecomeActive<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> name<span style="color: #002200;">:</span>UIApplicationDidBecomeActiveNotification object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add right after viewDidLoad</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>didBecomeActive<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span style="color: #400080;">NSNotification</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>notification <span style="color: #002200;">&#123;</span>    
    <span style="color: #002200;">&#91;</span>self refresh<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Run the app and perform the following steps:</p>
<ul>
<li>Make sure iCloud is off and create a local file.  Switch to settings and turn iCloud off.  You should no longer see the file.</li>
<li>Make sure iCloud is on and go to Settings\iCloud\Documents and Data and switch it off.  This effectively makes iCloud not available.  Switch back to the app and you should get a popup, and it should switch to iCloud off automatically.</li>
<li>Switch back to Settings and make iCloud available again.  Switch back to the app and it will tell you iCloud is available and ask if you want to turn it on.</li>
<li>Play around with switching iCoud on and off, ana make sure the appropriate &#8220;local => iCloud&#8221; or &#8220;iCloud => local&#8221; messages print out.</li>
</ul>
<p>Nice!  Now that we have this firm framework in place, all we really need to care about from here on out is whether &#8220;iCloudOn&#8221; is YES or NO.  If YES, we should be displaying iCloud files, otherwise local files.  </p>
<p>But we haven&#8217;t covered yet how to get a list of iCloud files.  Let&#8217;s cover that now!</p>
<h2>Querying iCloud Files</h2>
<p>As we mentioned in part 1, you can&#8217;t just enumerate the iCloud directory with NSFileManager APIs like you do for the documents directory.  Instead, you have to use a fancy API called NSMetadataQuery.</p>
<p>This API lets you set up a search on a directory, such as &#8220;give me all files that end with PTK&#8221;.  It will return the initial results, and then continue to watch the directory for you, sending you update notifications as they come in.  It&#8217;s pretty handy and efficient in comparison to the alternative (periodic polling).</p>
<p>Let&#8217;s see what it looks like.  Go to the &#8220;iCloud Query&#8221; section and add this right above startQuery:</p>

<div class="wp_codebox"><table><tr id="p1281648"><td class="code" id="p12816code48"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMetadataQuery_Class/"><span style="color: #400080;">NSMetadataQuery</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>documentQuery <span style="color: #002200;">&#123;</span>
&nbsp;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMetadataQuery_Class/"><span style="color: #400080;">NSMetadataQuery</span></a> <span style="color: #002200;">*</span> query <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMetadataQuery_Class/"><span style="color: #400080;">NSMetadataQuery</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>query<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Search documents subdir only</span>
        <span style="color: #002200;">&#91;</span>query setSearchScopes<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObject<span style="color: #002200;">:</span>NSMetadataQueryUbiquitousDocumentsScope<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Add a predicate for finding the documents</span>
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span> filePattern <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;*.%@&quot;</span>, PTK_EXTENSION<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>query setPredicate<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> predicateWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%K LIKE %@&quot;</span>,
                             NSMetadataItemFSNameKey, filePattern<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;        
&nbsp;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> query;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>When you create a NSMetadataQuery, you can tell it to watch the &#8220;Documents&#8221; subdirectory of the iCloud root (this is where we&#8217;ll be storing our files) by passing in NSMetadataQueryUbiquitousDocumentsScope as the search scope.  </p>
<p>You can then filter the output with a predicate.  We set up one here to look for files that end with the PTK extension.</p>
<p>Next let&#8217;s create some methods to start and stop this query.  Make the following changes to PTKMasterViewController.m:</p>

<div class="wp_codebox"><table><tr id="p1281649"><td class="code" id="p12816code49"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add new private instance variables</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMetadataQuery_Class/"><span style="color: #400080;">NSMetadataQuery</span></a> <span style="color: #002200;">*</span> _query;
<span style="color: #a61390;">BOOL</span> _iCloudURLsReady;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span> _iCloudURLs;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add to &quot;iCloud query&quot; section after documentQuery method, replacing the existing startQuery method</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>stopQuery <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_query<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;No longer watching iCloud dir...&quot;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> removeObserver<span style="color: #002200;">:</span>self name<span style="color: #002200;">:</span>NSMetadataQueryDidFinishGatheringNotification object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> removeObserver<span style="color: #002200;">:</span>self name<span style="color: #002200;">:</span>NSMetadataQueryDidUpdateNotification object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>_query stopQuery<span style="color: #002200;">&#93;</span>;
        _query <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>startQuery <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>self stopQuery<span style="color: #002200;">&#93;</span>;
&nbsp;
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Starting to watch iCloud dir...&quot;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    _query <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self documentQuery<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self
                                             selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>processiCloudFiles<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
                                                 name<span style="color: #002200;">:</span>NSMetadataQueryDidFinishGatheringNotification
                                               object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self
                                             selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>processiCloudFiles<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
                                                 name<span style="color: #002200;">:</span>NSMetadataQueryDidUpdateNotification
                                               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>_query startQuery<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add in viewDidLoad before call to refresh</span>
_iCloudURLs <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add at beginning of refresh method</span>
_iCloudURLsReady <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
<span style="color: #002200;">&#91;</span>_iCloudURLs removeAllObjects<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>startQuery gets the query and starts it up.  It also registers for two notifications &#8211; the initial gather notification, as well as further updates.  In both cases, processiCloudFiles will be called &#8211; we&#8217;ll write that next.  stopQuery just does the opposite and tears things down.</p>
<p>Continue by adding the implementation of processiCloudFiles:</p>

<div class="wp_codebox"><table><tr id="p1281650"><td class="code" id="p12816code50"><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>processiCloudFiles<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span style="color: #400080;">NSNotification</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>notification <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Always disable updates while processing results</span>
    <span style="color: #002200;">&#91;</span>_query disableUpdates<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>_iCloudURLs removeAllObjects<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// The query reports all files found, every time.</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span> queryResults <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_query results<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMetadataItem_Class/"><span style="color: #400080;">NSMetadataItem</span></a> <span style="color: #002200;">*</span> result <span style="color: #a61390;">in</span> queryResults<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> fileURL <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>result valueForAttribute<span style="color: #002200;">:</span>NSMetadataItemURLKey<span style="color: #002200;">&#93;</span>;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span style="color: #400080;">NSNumber</span></a> <span style="color: #002200;">*</span> aBool <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Don't include hidden files</span>
        <span style="color: #002200;">&#91;</span>fileURL getResourceValue<span style="color: #002200;">:&amp;</span>aBool forKey<span style="color: #002200;">:</span>NSURLIsHiddenKey error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>aBool <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>aBool boolValue<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #002200;">&#91;</span>_iCloudURLs addObject<span style="color: #002200;">:</span>fileURL<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>        
&nbsp;
    <span style="color: #002200;">&#125;</span>        
&nbsp;
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Found %d iCloud files.&quot;</span>, _iCloudURLs.count<span style="color: #002200;">&#41;</span>;
    _iCloudURLsReady <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self iCloudOn<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Remove deleted files</span>
        <span style="color: #11740a; font-style: italic;">// Iterate backwards because we need to remove items form the array</span>
        <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> _objects.count <span style="color: #002200;">-</span><span style="color: #2400d9;">1</span>; i &gt;<span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; <span style="color: #002200;">--</span>i<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            PTKEntry <span style="color: #002200;">*</span> entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_objects objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</span>;
            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>_iCloudURLs containsObject<span style="color: #002200;">:</span>entry.fileURL<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                <span style="color: #002200;">&#91;</span>self removeEntryWithURL<span style="color: #002200;">:</span>entry.fileURL<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span>
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Add new files</span>
        <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> fileURL <span style="color: #a61390;">in</span> _iCloudURLs<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>                
            <span style="color: #002200;">&#91;</span>self loadDocAtURL<span style="color: #002200;">:</span>fileURL<span style="color: #002200;">&#93;</span>;        
        <span style="color: #002200;">&#125;</span>
&nbsp;
        self.navigationItem.rightBarButtonItem.enabled <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span> 
&nbsp;
    <span style="color: #002200;">&#91;</span>_query enableUpdates<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>When you&#8217;re processing the results of an NSMetadataQuery, it&#8217;s important to stop the query so you don&#8217;t get more updates while you&#8217;re in the middle of processing the first, so we do that at the beginning and end of the method.</p>
<p>We then loop through the query results, and add everything to the list except for items that are hidden.  We add all of the results to the most up-to-date list of _iCloudURLs, which we will find handy later, and set a flag indicating that they are ready.</p>
<p>If iCloud isn&#8217;t on, that&#8217;s all we do.  But if it is on, we make sure our local list of entries matches the list of iCloud files.  We first loop through our entries and remove anything not in the list of iCloud files by calling removeEntryWithURL.  We also add anything that isn&#8217;t already in the list to the list by calling loadDocAtURL.  When this is all done it&#8217;s safe to add a new document again, so we enable the right bar button item.</p>
<p>Next, add these methods right after viewDidUnload:</p>

<div class="wp_codebox"><table><tr id="p1281651"><td class="code" id="p12816code51"><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>viewWillAppear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>_query enableUpdates<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewWillDisappear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>_query disableUpdates<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>This is important to add because UIDocument has issues if you try to open more than instance at a time pointing to the same fileURL, so we don&#8217;t want our table view trying to refresh itself (hence loading a UIDocument to get its medatata) while we&#8217;re editing a document.</p>
<p>We could run the app now but there wouldn&#8217;t be any use, as there&#8217;s no way to create a file in iCloud yet.  Luckily, since we already laid most of the groundwork by using UIDocument this is quite easy to fix!  Simply replace getDocURL with the following:</p>

<div class="wp_codebox"><table><tr id="p1281652"><td class="code" id="p12816code52"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>getDocURL<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>filename <span style="color: #002200;">&#123;</span>    
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self iCloudOn<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> docsDir <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_iCloudRoot URLByAppendingPathComponent<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Documents&quot;</span> isDirectory<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>docsDir URLByAppendingPathComponent<span style="color: #002200;">:</span>filename<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: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self.localRoot URLByAppendingPathComponent<span style="color: #002200;">:</span>filename<span style="color: #002200;">&#93;</span>;    
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Here we&#8217;ve implemented the &#8220;iCloudOn&#8221; case to return the Documents subdirectory of the iCloud root, where we will be saving our files.</p>
<p>When we go to create a new file, now it will be creating it in the iCloud directory, so the daemon will pick up on it and synchronize it.  Everything else will just work since we&#8217;re using UIDocument!</p>
<p>Compile and run on your device, and make sure iCloud is available and switched on.  Create some documents and verify that they are created in the iCloud directory by looking at the logs.  </p>
<p>Now for the fun part &#8211; start up a second device and you should see the same files pull down from iCloud!  :D</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/2Devices.jpg"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/2Devices.jpg" alt="iCloud Synchronizing across 2 Devices" title="iCloud Synchronizing across 2 Devices" width="497" height="322" class="alignnone size-full wp-image-12831" /></a></p>
<p>If you have any troubles, try deleting the app from your device and re-installing, double checking that your Document exports are set up properly, or compare your project to the solution at the end of this tutorial.</p>
<h2>Fixing Deleting</h2>
<p>If you try deleting a file right now, it may work, but it&#8217;s currently doing things in an unsafe way according to the <a href="https://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/DocumentBasedAppPGiOS/ManageDocumentLifeCycle/ManageDocumentLifeCycle.html#//apple_ref/doc/uid/TP40011149-CH4-SW4">Document-Based App Programming Guide</a>.</p>
<p>When you&#8217;re dealing with files in an iCloud directory, you can&#8217;t just use NSFileManager APIs directly like you could with local files.  Instead, you have to use the NSFileCoordinator class to make sure it&#8217;s safe to modify the files.  This is important since the iCloud daemon is also working with this directory at the same time.</p>
<p>To see what this looks like, open PTKMasterViewController.m and replace deleteEntry with the following:</p>

<div class="wp_codebox"><table><tr id="p1281653"><td class="code" id="p12816code53"><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>deleteEntry<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>PTKEntry <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>entry <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Wrap in file coordinator</span>
    dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_global_queue<span style="color: #002200;">&#40;</span>DISPATCH_QUEUE_PRIORITY_DEFAULT, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        NSFileCoordinator<span style="color: #002200;">*</span> fileCoordinator <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSFileCoordinator alloc<span style="color: #002200;">&#93;</span> initWithFilePresenter<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>fileCoordinator coordinateWritingItemAtURL<span style="color: #002200;">:</span>entry.fileURL 
                                            options<span style="color: #002200;">:</span>NSFileCoordinatorWritingForDeleting
                                              error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> 
                                         byAccessor<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a><span style="color: #002200;">*</span> writingURL<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>                                                   
                                             <span style="color: #11740a; font-style: italic;">// Simple delete to start</span>
                                             <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a><span style="color: #002200;">*</span> fileManager <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
                                             <span style="color: #002200;">&#91;</span>fileManager removeItemAtURL<span style="color: #002200;">:</span>entry.fileURL error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
                                         <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;    
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Fixup view</span>
    <span style="color: #002200;">&#91;</span>self removeEntryWithURL<span style="color: #002200;">:</span>entry.fileURL<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span></pre></td></tr></table></div>

<p>Here we create a NSFileCoordinator and use the coordinateWritingAtURL method passing in NSFileCoordinatorWritingForDeletign to make sure we have access to delete the file.  This method may block, so it&#8217;s important to run it on a background thread.  Once we have access, it&#8217;s safe to delete it as usual.</p>
<p>Compile and run, and now you should be able to delete entries &#8211; but safely this time!</p>
<h2>Fixing Renaming</h2>
<p>Similarly, we need to fix up renaming.  In the renameEntry method, replace the &#8220;Simple renaming to start&#8221; section with the following:</p>

<div class="wp_codebox"><table><tr id="p1281654"><td class="code" id="p12816code54"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Wrap in file coordinator</span>
dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_global_queue<span style="color: #002200;">&#40;</span>DISPATCH_QUEUE_PRIORITY_DEFAULT, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span> error;
    NSFileCoordinator <span style="color: #002200;">*</span>coordinator <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSFileCoordinator alloc<span style="color: #002200;">&#93;</span> initWithFilePresenter<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>coordinator coordinateWritingItemAtURL<span style="color: #002200;">:</span>entry.fileURL options<span style="color: #002200;">:</span> NSFileCoordinatorWritingForMoving writingItemAtURL<span style="color: #002200;">:</span>newDocURL options<span style="color: #002200;">:</span> NSFileCoordinatorWritingForReplacing error<span style="color: #002200;">:&amp;</span>error byAccessor<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span>newURL1, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span>newURL2<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Simple renaming to start</span>
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a><span style="color: #002200;">*</span> fileManager <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span> error;
        <span style="color: #a61390;">BOOL</span> success <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>fileManager moveItemAtURL<span style="color: #002200;">:</span>entry.fileURL toURL<span style="color: #002200;">:</span>newDocURL error<span style="color: #002200;">:&amp;</span>error<span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Failed to move file: %@&quot;</span>, error.localizedDescription<span style="color: #002200;">&#41;</span>;
            <span style="color: #a61390;">return</span>;
        <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>This is exactly the same as we did for deleting files, except we call a slightly different method on NSFileCoordinator with parameters for moving a file.</p>
<p>Compile and run, and try to create a file, and&#8230; wait, it doesn&#8217;t work!  The console shows the following:</p>
<pre class="command">
Failed to move file: The operation couldn‚Äôt be completed. (Cocoa error 4.)
</pre>
<p>To be honest, I have no idea why we get this error &#8211; it seems to me that this should work.  If anyone knows (maybe I have passed the wrong parameters to coordinateWritingItemAtURL:entry.fileURL?) let me know.  </p>
<p>In the meantime, I have another method that works (although is slightly hackish) &#8211; save the old file to a new filename, and delete the old file.  Try it out by replacing the above code block with the following:</p>

<div class="wp_codebox"><table><tr id="p1281655"><td class="code" id="p12816code55"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Rename by saving/deleting - hack?</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> origURL <span style="color: #002200;">=</span> entry.fileURL;
UIDocument <span style="color: #002200;">*</span> doc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PTKDocument alloc<span style="color: #002200;">&#93;</span> initWithFileURL<span style="color: #002200;">:</span>entry.fileURL<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>doc openWithCompletionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>doc saveToURL<span style="color: #002200;">:</span>newDocURL forSaveOperation<span style="color: #002200;">:</span>UIDocumentSaveForCreating completionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Doc saved to %@&quot;</span>, newDocURL<span style="color: #002200;">&#41;</span>;                        
        <span style="color: #002200;">&#91;</span>doc closeWithCompletionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Update version of file</span>
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
                entry.version <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSFileVersion currentVersionOfItemAtURL<span style="color: #002200;">:</span>newDocURL<span style="color: #002200;">&#93;</span>;
                <span style="color: #a61390;">int</span> index <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self indexOfEntryWithFileURL<span style="color: #002200;">:</span>entry.fileURL<span style="color: #002200;">&#93;</span>;
                <span style="color: #002200;">&#91;</span>self.tableView reloadRowsAtIndexPaths<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> indexPathForRow<span style="color: #002200;">:</span>index inSection<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> withRowAnimation<span style="color: #002200;">:</span>UITableViewRowAnimationNone<span style="color: #002200;">&#93;</span>;    
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;                
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Delete old file</span>
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_global_queue<span style="color: #002200;">&#40;</span>DISPATCH_QUEUE_PRIORITY_DEFAULT, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                NSFileCoordinator<span style="color: #002200;">*</span> fileCoordinator <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSFileCoordinator alloc<span style="color: #002200;">&#93;</span> initWithFilePresenter<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
                <span style="color: #002200;">&#91;</span>fileCoordinator coordinateWritingItemAtURL<span style="color: #002200;">:</span>origURL 
                                                    options<span style="color: #002200;">:</span>NSFileCoordinatorWritingForDeleting
                                                      error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> 
                                                 byAccessor<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a><span style="color: #002200;">*</span> writingURL<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>                                                   
                                                     <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a><span style="color: #002200;">*</span> fileManager <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
                                                     <span style="color: #002200;">&#91;</span>fileManager removeItemAtURL<span style="color: #002200;">:</span>writingURL error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
                                                 <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Doc deleted at %@&quot;</span>, origURL<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Compile and run, and you should now be able to rename files at will!</p>
<p>Note that the way the app is currently designed, when you rename a file it will disappear temporarily (because the old file was deleted) and reappear a second later (as the new file is noticed and opened).  This is because our table view is refreshed upon the results of the NSMetadataQuery.  If anyone has a better strategy to deal with updates to avoid this problem, please drop a note in the forum discussion!</p>
<h2>Detecting Updates</h2>
<p>The last thing we&#8217;ll cover in this part of the tutorial is detecting updates to an opened document.  Right now, if you open the same document on two devices and change the photo on one of the devies, the other device won&#8217;t notice that it&#8217;s changed.</p>
<p>Luckily, UIDocument has built-in support to notice changes and update itself behind the scenes!  All we need to do is register for a notification when this occurs so we can update the detail view controller.</p>
<p>Open PTKDetailViewController.m and add these methods right after shouldAutorotateToInterfaceOrientation:</p>

<div class="wp_codebox"><table><tr id="p1281656"><td class="code" id="p12816code56"><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>viewWillAppear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self
                                             selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>documentStateChanged<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
                                                 name<span style="color: #002200;">:</span>UIDocumentStateChangedNotification 
                                               object<span style="color: #002200;">:</span>self.doc<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewWillDisappear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> removeObserver<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>documentStateChanged<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span style="color: #400080;">NSNotification</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>notificaiton <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>self configureView<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Here we just wait for the UIDocumentStateChangedNotification notification and refresh the view if it occurs.  Pretty simple, eh?</p>
<p>Compile and run on two devices, and open the same document on two devices.  Now when you modify the document on device 1, the second device will notice and update as well!</p>
<h2>Where To Go From Here?</h2>
<p>Here is a download with the state of the <a href="http://d1xzuxjlafny7l.cloudfront.net/downloads/PhotoKeeper3.zip">code sample</a> so far.</p>
<p>At this point, this app is fully functional for local documents, mostly functional for iCloud documents (with full create, read, update, delete support), and allows you to toggle back and forth between the two options in Settings.</p>
<p>However, there are still some subtle aspects remaining that we need to address.  We need to implement those methods to move documents to and from iCloud when the user switches iCloud on or off, and we need to deal with the dreaded iCloud conflicts!</p>
<p>So stay tuned for the final part of this tutorial series, where we will cover those topics.  In the meantime, if you have any comments, questions, or suggestions for improvement please join the forum discussion below!</p>
<p><img src="http://d1xzuxjlafny7l.cloudfront.net/downloads/RayWenderlich.jpg" class="photo alignleft" /><br />
<i>This is a blog post by site administrator <a href="http://www.raywenderlich.com/about">Ray Wenderlich</a>, an independent software developer and gamer.</i></p>
<p><a href="http://www.raywenderlich.com/12816/icloud-and-uidocument-beyond-the-basics-part-3">iCloud and UIDocument: Beyond the Basics. Part 3/4</a> is a post from: <a href="http://www.raywenderlich.com">Ray Wenderlich</a></p>
<div id="tweetbutton12816" class="tw_button" style="float:left;"><a href="http://twitter.com/share?url=http%3A%2F%2Fbit.ly%2FInWTvc&amp;via=rwenderlich&amp;text=iCloud%20and%20UIDocument%3A%20Beyond%20the%20Basics.%20Part%203%2F4&amp;related=rwenderlich&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fwww.raywenderlich.com%2F12816%2Ficloud-and-uidocument-beyond-the-basics-part-3" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://d1xzuxjlafny7l.cloudfront.net/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><img src="http://feeds.feedburner.com/~r/RayWenderlich/~4/1tWQctUiN0o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.raywenderlich.com/12816/icloud-and-uidocument-beyond-the-basics-part-3/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.raywenderlich.com/12816/icloud-and-uidocument-beyond-the-basics-part-3</feedburner:origLink></item>
		<item>
		<title>iCloud and UIDocument: Beyond the Basics. Part 2/4</title>
		<link>http://feedproxy.google.com/~r/RayWenderlich/~3/Lj881StOveM/icloud-and-uidocument-beyond-the-basics-part-2</link>
		<comments>http://www.raywenderlich.com/12794/icloud-and-uidocument-beyond-the-basics-part-2#comments</comments>
		<pubDate>Tue, 08 May 2012 15:00:05 +0000</pubDate>
		<dc:creator>Ray Wenderlich</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iCloud]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[ios5]]></category>
		<category><![CDATA[sample code]]></category>
		<category><![CDATA[storyboards]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[UIKit]]></category>

		<guid isPermaLink="false">http://www.raywenderlich.com/?p=12794</guid>
		<description><![CDATA[TweetThis is a blog post by site administrator Ray Wenderlich, an independent software developer and gamer. Welcome back to our [...]<p><a href="http://www.raywenderlich.com/12794/icloud-and-uidocument-beyond-the-basics-part-2">iCloud and UIDocument: Beyond the Basics. Part 2/4</a> is a post from: <a href="http://www.raywenderlich.com">Ray Wenderlich</a></p>
]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton12794" class="tw_button" style="float:left;"><a href="http://twitter.com/share?url=http%3A%2F%2Fbit.ly%2FJKLOWk&amp;via=rwenderlich&amp;text=iCloud%20and%20UIDocument%3A%20Beyond%20the%20Basics.%20Part%202%2F4&amp;related=rwenderlich&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fwww.raywenderlich.com%2F12794%2Ficloud-and-uidocument-beyond-the-basics-part-2" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://d1xzuxjlafny7l.cloudfront.net/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><div id="attachment_12780" class="wp-caption alignright" style="width: 292px"><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/iCloudTutorial.jpg"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/iCloudTutorial-282x320.jpg" alt="Learn how to make a complete UIDocument + iCloud app!" title="Learn how to make a complete UIDocument + iCloud app!" width="282" height="320" class="size-medium wp-image-12780" /></a><p class="wp-caption-text">Learn how to make a complete UIDocument + iCloud app!</p></div>
<p><i>This is a blog post by site administrator <a href="http://www.raywenderlich.com/about">Ray Wenderlich</a>, an independent software developer and gamer.</i></p>
<p>Welcome back to our document-based iCloud app tutorial series!</p>
<p>In this tutorial series we are making a complete document-based iCloud app called PhotoKeeper, with features that go beyond just the basics.</p>
<p>In the <a href="http://www.raywenderlich.com/12779/icloud-and-uidocument-beyond-the-basics-part-1">first part of the series</a>, we created model classes for our app and a UIDocument wrapper.  We also added logic to list and add local files.</p>
<p>In this second part of the series, we will make the app fully functional when it comes to local files.  We will improve the look of our master view, implement the detail view, and add support for renaming and deleting files.</p>
<p>If you&#8217;re eager to get into iCloud, don&#8217;t worry &#8211; getting UIDocument support working like we&#8217;re doing here is a prerequisite!  We&#8217;re laying a framework that will make switching to iCloud much easier.</p>
<p>This project continues where we left off last time, so if you don&#8217;t have it already grab the previous <a href="http://d1xzuxjlafny7l.cloudfront.net/downloads/PhotoKeeper1.zip">code sample</a> and open up the project.  Let&#8217;s begin!<span id="more-12794"></span><br />
<h2>A Better Table View</h2>
<p>Right now our table view is the boring default style that the template made for us.  Let&#8217;s fix this up so it&#8217;s more the way we want for PhotoKeeper.</p>
<p>Open MainStoryboard.storyboard and select the Table View inside the Master View Controller.  Switch to the Size Inspector, and set the Row Height to 80:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingRowHeight.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingRowHeight-700x278.png" alt="Setting row height of a table view" title="Setting row height of a table view" width="700" height="278" class="size-large wp-image-12798" /></a></p>
<p>Next select the Table View Cell and set the Style to Custom to remove the default controls:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SetCellToCustom.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SetCellToCustom-700x300.png" alt="Setting cell type to custom" title="Setting cell type to custom" width="700" height="300" class="size-large wp-image-12799" /></a></p>
<p>Drag a UIImageView, UITextField, and UILabel into the cell so it looks roughly like the following:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/AddingControls.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/AddingControls.png" alt="Adding controls to a UITableViewCell" title="Adding controls to a UITableViewCell" width="639" height="243" class="size-full wp-image-12800" /></a></p>
<p>Note we are adding a UITextField instead of a UILabel for the document name so that later we can implement renaming the document.</p>
<p>Speaking of the UITextField &#8211; select it and go to the Attributes Inspector.  Set the Border Style to None, Clear Button to Appears while editing, the Font to System 17.0, Capitalization to Words, and Correction to No:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/UITextFieldSettings.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/UITextFieldSettings-700x292.png" alt="Modifying UITextField settings" title="Modifying UITextField settings" width="700" height="292" class="size-large wp-image-12801" /></a></p>
<p>To nicely support landscape orientation, set the autosizing attributes of the text field and label as follows:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingAutosizing.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingAutosizing-700x290.png" alt="Setting autosizing attributes" title="Setting autosizing attributes" width="700" height="290" class="size-large wp-image-12802" /></a></p>
<p>To fill in our controls, we need a way to access them via code.  We could get them from the cell by tag, but to keep our code cleaner and easier to read we will make a custom UITableView sublass instead.</p>
<p>Create a new file with the iOS\Cocoa Touch\Objective-C class template, name it PTKEntryCell, and make it a subclass of UITableViewCell.  Then replace the contents of PTKEntryCell.h with the following:</p>

<div class="wp_codebox"><table><tr id="p1279470"><td class="code" id="p12794code70"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;UIKit/UIKit.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> PTKEntryCell <span style="color: #002200;">:</span> UITableViewCell
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>weak, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UIImageView <span style="color: #002200;">*</span> photoImageView;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>weak, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UITextField <span style="color: #002200;">*</span> titleTextField;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>weak, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UILabel <span style="color: #002200;">*</span> subtitleLabel;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Here we make outlets for the controls in our cell, and also add a delegate that we can notify when the user edits the text.</p>
<p>While you&#8217;re at it switch to PTKEntryCell.m and replace the contents with the following:</p>

<div class="wp_codebox"><table><tr id="p1279471"><td class="code" id="p12794code71"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;PTKEntryCell.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> PTKEntryCell
<span style="color: #a61390;">@synthesize</span> photoImageView;
<span style="color: #a61390;">@synthesize</span> titleTextField;
<span style="color: #a61390;">@synthesize</span> subtitleLabel;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setEditing<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>editing animated<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super setEditing<span style="color: #002200;">:</span>editing animated<span style="color: #002200;">:</span>animated<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>UIView animateWithDuration<span style="color: #002200;">:</span><span style="color: #2400d9;">0.1</span> animations<span style="color: #002200;">:^</span><span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>editing<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span>
            titleTextField.enabled <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
            titleTextField.borderStyle <span style="color: #002200;">=</span> UITextBorderStyleRoundedRect;
        <span style="color: #002200;">&#125;</span><span style="color: #a61390;">else</span><span style="color: #002200;">&#123;</span>
            titleTextField.enabled <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
            titleTextField.borderStyle <span style="color: #002200;">=</span> UITextBorderStyleNone;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Here we implement setEditing in order to switch our text field into editing mode or not based on whether the cell is in editing mode.</p>
<p>Now let&#8217;s configure our table view to use this custom cell class in the Storyboard editor.  Open MainStoryboard.storyboard, select the cell, and in the identity inspector set it to PTKEntryCell:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingCellClass.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingCellClass-700x196.png" alt="Setting the cell class in the Identity Inspector" title="Setting the cell class in the Identity Inspector" width="700" height="196" class="size-large wp-image-12803" /></a></p>
<p>Now control-drag from the cell to the image view, text field, and label controls, connecting them to the photoImageView, titleTextField, and subtitleLabel outlets.</p>
<p>Let&#8217;s set up the master view controller to use this cell now.  Open PTKMasterViewController.h and mark the class as implementing UITextFieldDelegate:</p>

<div class="wp_codebox"><table><tr id="p1279472"><td class="code" id="p12794code72"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;UIKit/UIKit.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> PTKMasterViewController <span style="color: #002200;">:</span> UITableViewController &lt;UITextFieldDelegate&gt;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Then switch to PTKMasterViewController.m and import PTKEntryCell.h at the top of the file:</p>

<div class="wp_codebox"><table><tr id="p1279473"><td class="code" id="p12794code73"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;PTKEntryCell.h&quot;</span></pre></td></tr></table></div>

<p>And replace tableView:cellForRowAtIndexPath: with the following:</p>

<div class="wp_codebox"><table><tr id="p1279474"><td class="code" id="p12794code74"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>UITableViewCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView cellForRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
    PTKEntryCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>tableView dequeueReusableCellWithIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cell&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    PTKEntry <span style="color: #002200;">*</span>entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_objects objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
&nbsp;
    cell.titleTextField.text <span style="color: #002200;">=</span> entry.description;
    cell.titleTextField.delegate <span style="color: #002200;">=</span> self;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>entry.metadata <span style="color: #002200;">&amp;&amp;</span> entry.metadata.thumbnail<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        cell.photoImageView.image <span style="color: #002200;">=</span> entry.metadata.thumbnail;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        cell.photoImageView.image <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>entry.version<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        cell.subtitleLabel.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>entry.version.modificationDate mediumString<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        cell.subtitleLabel.text <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> cell;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>This is similar to what we had before, except we are setting the controls in our new PTKEntryCell.  We&#8217;ll implement the delegate callback later so don&#8217;t worry about it for now.</p>
<p>That&#8217;s it &#8211; compile and run, and now the app&#8217;s looking a bit better!  </p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/CustomCells.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/CustomCells.png" alt="PhotoKeeper displaying custom cells" title="PhotoKeeper displaying custom cells" width="320" height="480" class="size-full wp-image-12804 bordered" /></a></p>
<p>It doesn&#8217;t show photos yet (since we had no way to set photos), but that&#8217;s what we&#8217;ll do next :]</p>
<h2>Creating the Detail View</h2>
<p>Right now our detail view doesn&#8217;t work &#8211; it&#8217;s just the default detail view created for us by the template.  Let&#8217;s fix that up.</p>
<p>Open MainStoryboard.storyboard and find the Detail View Controller.  Delete the label that&#8217;s in the middle, and add a big old UIImageView filling up the entire view:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/AddingImageView.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/AddingImageView.png" alt="Adding an image view to a view controller" title="Adding an image view to a view controller" width="633" height="503" class="size-full wp-image-12805" /></a></p>
<p>Open up the Assistant Editor, make sure that PTKDetailViewController.h is visible in the assistant editor, and control-drag from the image view below the @interface.  Enter imageView for the name, and click Connect.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/ConnectingOutlet.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/ConnectingOutlet-700x177.png" alt="Connecting the image view to an outlet" title="Connecting the image view to an outlet" width="700" height="177" class="size-large wp-image-12806" /></a></p>
<p>Next switch to PTKDetailViewController.h and modify the file so it looks like the following:</p>

<div class="wp_codebox"><table><tr id="p1279475"><td class="code" id="p12794code75"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;UIKit/UIKit.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@class</span> PTKDocument;
<span style="color: #a61390;">@class</span> PTKDetailViewController;
&nbsp;
<span style="color: #a61390;">@protocol</span> PTKDetailViewControllerDelegate 
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>detailViewControllerDidClose<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>PTKDetailViewController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>detailViewController;
<span style="color: #a61390;">@end</span>
&nbsp;
<span style="color: #a61390;">@interface</span> PTKDetailViewController <span style="color: #002200;">:</span> UIViewController &lt;UIImagePickerControllerDelegate, UINavigationControllerDelegate&gt;
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong, nonatomic<span style="color: #002200;">&#41;</span> PTKDocument <span style="color: #002200;">*</span> doc;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>weak, nonatomic<span style="color: #002200;">&#41;</span> IBOutlet UIImageView <span style="color: #002200;">*</span>imageView;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>weak<span style="color: #002200;">&#41;</span> <span style="color: #a61390;">id</span> &lt;PTKDetailViewControllerDelegate&gt; delegate;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Here we added a protocol/delegate which we can notify when the user is done, added a property of the (opened) PTKDocument we should display, and marked our class as implementing two protocols we&#8217;ll need to use an image picker.</p>
<p>Note that we are passing an opened PTKDocument as the item to display (rather than the fileURL).  This was a design decision.  It can take time to open a document, especially if it is large or not fully synchronized with iCloud, and it depends where you want to spend that time &#8211; before transitioning to the detail view or after.  We chose before for this.</p>
<p>Next switch to PTKDetailViewController.m and replace it with the following.  Note I am giving a lot of code at once here, but this is pretty simple stuff so it should be OK.</p>

<div class="wp_codebox"><table><tr id="p1279476"><td class="code" id="p12794code76"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;PTKDetailViewController.h&quot;</span>
<span style="color: #6e371a;">#import &quot;PTKDocument.h&quot;</span>
<span style="color: #6e371a;">#import &quot;PTKData.h&quot;</span>
<span style="color: #6e371a;">#import &quot;UIImageExtras.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> PTKDetailViewController <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>configureView;
<span style="color: #a61390;">@end</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> PTKDetailViewController <span style="color: #002200;">&#123;</span>
    UIImagePickerController <span style="color: #002200;">*</span> _picker;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@synthesize</span> doc <span style="color: #002200;">=</span> _doc;
<span style="color: #a61390;">@synthesize</span> imageView <span style="color: #002200;">=</span> _imageView;
<span style="color: #a61390;">@synthesize</span> delegate <span style="color: #002200;">=</span> _delegate;
&nbsp;
<span style="color: #6e371a;">#pragma mark - Managing the detail item</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>setDoc<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>newDoc
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_doc <span style="color: #002200;">!=</span> newDoc<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        _doc <span style="color: #002200;">=</span> newDoc;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Update the view.</span>
        <span style="color: #002200;">&#91;</span>self configureView<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>configureView
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Update the user interface for the detail item.</span>
    self.title <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self.doc description<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>self.doc.photo<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        self.imageView.image <span style="color: #002200;">=</span> self.doc.photo;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        self.imageView.image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIImage imageNamed<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;defaultImage.png&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
	<span style="color: #11740a; font-style: italic;">// Do any additional setup after loading the view, typically from a nib.</span>
&nbsp;
    UIBarButtonItem <span style="color: #002200;">*</span>backButtonItem <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIBarButtonItem alloc<span style="color: #002200;">&#93;</span> initWithBarButtonSystemItem<span style="color: #002200;">:</span>UIBarButtonSystemItemDone target<span style="color: #002200;">:</span>self action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>doneTapped<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
    self.navigationItem.leftBarButtonItem <span style="color: #002200;">=</span> backButtonItem;
    <span style="color: #002200;">&#91;</span>self.navigationItem setHidesBackButton<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span> animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    UITapGestureRecognizer <span style="color: #002200;">*</span> tapRecognizer <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>imageTapped<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self.view addGestureRecognizer<span style="color: #002200;">:</span>tapRecognizer<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>self configureView<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidUnload
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>self setImageView<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>super viewDidUnload<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>shouldAutorotateToInterfaceOrientation<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIInterfaceOrientation<span style="color: #002200;">&#41;</span>interfaceOrientation
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#40;</span>interfaceOrientation <span style="color: #002200;">!=</span> UIInterfaceOrientationPortraitUpsideDown<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark Callbacks</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>imageTapped<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITapGestureRecognizer <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>recognizer <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>_picker<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        _picker <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIImagePickerController alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
        _picker.delegate <span style="color: #002200;">=</span> self;
        _picker.sourceType <span style="color: #002200;">=</span> UIImagePickerControllerSourceTypePhotoLibrary;
        _picker.allowsEditing <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>self presentModalViewController<span style="color: #002200;">:</span>_picker animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</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: #a61390;">void</span><span style="color: #002200;">&#41;</span>doneTapped<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>
&nbsp;
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Closing %@...&quot;</span>, self.doc.fileURL<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>self.doc saveToURL<span style="color: #002200;">:</span>self.doc.fileURL forSaveOperation<span style="color: #002200;">:</span>UIDocumentSaveForOverwriting completionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>self.doc closeWithCompletionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>                        
                <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Failed to close %@&quot;</span>, self.doc.fileURL<span style="color: #002200;">&#41;</span>;
                    <span style="color: #11740a; font-style: italic;">// Continue anyway...</span>
                <span style="color: #002200;">&#125;</span>
&nbsp;
                <span style="color: #002200;">&#91;</span>self.delegate detailViewControllerDidClose<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark UIImagePickeerControllerDelegate</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>imagePickerControllerDidCancel<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIImagePickerController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>picker <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>self dismissViewControllerAnimated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span> completion<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>imagePickerController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIImagePickerController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>picker didFinishPickingMediaWithInfo<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>info <span style="color: #002200;">&#123;</span>    
&nbsp;
    UIImage <span style="color: #002200;">*</span>image <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#91;</span>info objectForKey<span style="color: #002200;">:</span>UIImagePickerControllerOriginalImage<span style="color: #002200;">&#93;</span>;
&nbsp;
    CGSize mainSize <span style="color: #002200;">=</span> self.imageView.bounds.size;
    UIImage <span style="color: #002200;">*</span>sImage <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>image imageByBestFitForSize<span style="color: #002200;">:</span>mainSize<span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">//[image scaleToFitSize:mainSize];</span>
&nbsp;
    self.doc.photo <span style="color: #002200;">=</span> sImage;
    self.imageView.image <span style="color: #002200;">=</span> sImage;
&nbsp;
    <span style="color: #002200;">&#91;</span>self dismissViewControllerAnimated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span> completion<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Read through this and make sure you understand what&#8217;s going on.  There are just a few things to point out here:</p>
<ul>
<li>When the user changes the image, we change it in the document immediately via the setter we wrote earlier.  Since the setter uses the undo manager, UIDocument knows about the change so will auto-save the document at some point in the future.</li>
<li>When the done button is tapped, we close the document.  This triggers a save if it hasn&#8217;t been auto-saved already.  We notify the delegate when we&#8217;re done so they can dismiss us.</li>
</ul>
<p>Almost done &#8211; just need to make the master view controller use this.  First, right now the template has made is so when a row is tapped a segue is automatically performed (bypassing tableView:didSelectRowAtIndexPath).  We first need to modify this so tableView:didSelectRowAtIndexPath is called first, so we have a chance to open the document before performing the segue.</p>
<p>To fix this, open MainStoryboard.storyboard and delete the segue between the master view controller and the detail view controller.  Then control-drag from the master view controller (NOT the table view cell) to the detail view controller, and choose Push from the segue popup.  Then select the segue and name it showDetail:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/FixingSegue.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/FixingSegue-700x324.png" alt="Fixing the Segue" title="Fixing the Segue" width="700" height="324" class="size-large wp-image-12807" /></a></p>
<p>Next open PTKMasterViewController.h and mark the class as implementing the detail view controller delegate:</p>

<div class="wp_codebox"><table><tr id="p1279477"><td class="code" id="p12794code77"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;UIKit/UIKit.h&gt;</span>
<span style="color: #6e371a;">#import &quot;PTKEntryCell.h&quot;</span>
<span style="color: #6e371a;">#import &quot;PTKDetailViewController.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> PTKMasterViewController <span style="color: #002200;">:</span> UITableViewController &lt;UITextFieldDelegate, PTKDetailViewControllerDelegate&gt;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Then switch to PTKMasterViewController.m and make the following changes:</p>

<div class="wp_codebox"><table><tr id="p1279478"><td class="code" id="p12794code78"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// 1) Add right above the &quot;View lifecycle&quot; section with awakeFromNib</span>
<span style="color: #6e371a;">#pragma mark PTKDetailViewControllerDelegate</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>detailViewControllerDidClose<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>PTKDetailViewController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>detailViewController <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>self.navigationController popViewControllerAnimated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    NSFileVersion <span style="color: #002200;">*</span> version <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSFileVersion currentVersionOfItemAtURL<span style="color: #002200;">:</span>detailViewController.doc.fileURL<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self addOrUpdateEntryWithURL<span style="color: #002200;">:</span>detailViewController.doc.fileURL metadata<span style="color: #002200;">:</span>detailViewController.doc.metadata state<span style="color: #002200;">:</span>detailViewController.doc.documentState version<span style="color: #002200;">:</span>version<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// 2) Add right above prepareForSegue</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView didSelectRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath <span style="color: #002200;">&#123;</span>
&nbsp;
    PTKEntry <span style="color: #002200;">*</span> entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_objects objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self.tableView deselectRowAtIndexPath<span style="color: #002200;">:</span>indexPath animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    _selDocument <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PTKDocument alloc<span style="color: #002200;">&#93;</span> initWithFileURL<span style="color: #002200;">:</span>entry.fileURL<span style="color: #002200;">&#93;</span>;    
    <span style="color: #002200;">&#91;</span>_selDocument openWithCompletionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
            <span style="color: #002200;">&#91;</span>self performSegueWithIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;showDetail&quot;</span> sender<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;            
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// 3) Replace prepareForSegue with the following</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>prepareForSegue<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIStoryboardSegue <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>segue sender<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: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>segue identifier<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;showDetail&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>segue destinationViewController<span style="color: #002200;">&#93;</span> setDelegate<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>segue destinationViewController<span style="color: #002200;">&#93;</span> setDoc<span style="color: #002200;">:</span>_selDocument<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> 
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Let&#8217;s go through these methods one by one:</p>
<ol>
<li>When the detail view is done, we pop the view controller and refresh our table view entry.</li>
<li>When a row is selected, we open the document and perform the segue once it&#8217;s loaded.</li>
<li>When a segue is performed, we pass the document to be edited to the detail view, and also set ourselves as its delegate.</li>
</ol>
<p>If you&#8217;re still rusty with the concept of segues, you might want to check out our <a href="http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1">storyboard tutorial</a>.</p>
<p>That&#8217;s it!  Compile and run, and now you can set photos on your documents and they will persist even if you shut down/restart the app!</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingPhotos.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/SettingPhotos.png" alt="Setting the photos in PhotoKeeper" title="Setting the photos in PhotoKeeper" width="320" height="480" class="size-full wp-image-12808 bordered" /></a></p>
<h2>Deleting Documents</h2>
<p>Hey, we&#8217;re getting pretty close to a functional app here!  But right now although we can create files, we can&#8217;t delete flies.  Let&#8217;s add that real quick.</p>
<p>Make the following changes to PTKMasterViewController.m:</p>

<div class="wp_codebox"><table><tr id="p1279479"><td class="code" id="p12794code79"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add to end of &quot;Entry management methods&quot; section</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>removeEntryWithURL<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>fileURL <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">int</span> index <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self indexOfEntryWithFileURL<span style="color: #002200;">:</span>fileURL<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>_objects removeObjectAtIndex<span style="color: #002200;">:</span>index<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self.tableView deleteRowsAtIndexPaths<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> indexPathForRow<span style="color: #002200;">:</span>index inSection<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> withRowAnimation<span style="color: #002200;">:</span>UITableViewRowAnimationLeft<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add at end of &quot;File management methods&quot; section</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>deleteEntry<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>PTKEntry <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>entry <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Simple delete to start</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a><span style="color: #002200;">*</span> fileManager <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>fileManager removeItemAtURL<span style="color: #002200;">:</span>entry.fileURL error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Fixup view</span>
    <span style="color: #002200;">&#91;</span>self removeEntryWithURL<span style="color: #002200;">:</span>entry.fileURL<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Replace tableView:commitEditingStyle:forRowAtIndexPath</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView commitEditingStyle<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableViewCellEditingStyle<span style="color: #002200;">&#41;</span>editingStyle forRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>editingStyle <span style="color: #002200;">==</span> UITableViewCellEditingStyleDelete<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>                
        PTKEntry <span style="color: #002200;">*</span> entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_objects objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>self deleteEntry<span style="color: #002200;">:</span>entry<span style="color: #002200;">&#93;</span>;        
    <span style="color: #002200;">&#125;</span> 
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>The only part worth mentioning here is the delete itself is performed by NSFileManager&#8217;s removeItemAtURL method.  This will cause problems with iCloud as-is but will work fine for local docs, so we&#8217;ll keep it this way for now.</p>
<p>Compile and run, and now you can swipe rows to permanently delete them!  Be sure to shut down and restart the app to verify they are gone for good.</p>
<h2>Renaming Documents</h2>
<p>Next we need to add a way for users to rename their files rather than always having &#8220;Photo&#8221;, &#8220;Photo 1&#8243;, etc.</p>
<p>First let&#8217;s add a method to rename an entry to a given filename.  Add this method to PTKMasterViewController.m to the &#8220;Entry management methods&#8221; section, right below addOrUpdateEntryWithURL:metadata:state:version:</p>

<div class="wp_codebox"><table><tr id="p1279480"><td class="code" id="p12794code80"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>renameEntry<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>PTKEntry <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>entry to<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>filename <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Bail if not actually renaming</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>entry.description isEqualToString<span style="color: #002200;">:</span>filename<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Check if can rename file</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span> newDocFilename <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@.%@&quot;</span>,
                                 filename, PTK_EXTENSION<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self docNameExistsInObjects<span style="color: #002200;">:</span>newDocFilename<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span> message <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;<span style="color: #2400d9;">\&quot;</span>%@<span style="color: #2400d9;">\&quot;</span> is already taken.  Please choose a different name.&quot;</span>, filename<span style="color: #002200;">&#93;</span>;
        UIAlertView <span style="color: #002200;">*</span> alertView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> message<span style="color: #002200;">:</span>message delegate<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;OK&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>alertView show<span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> newDocURL <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self getDocURL<span style="color: #002200;">:</span>newDocFilename<span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Moving %@ to %@&quot;</span>, entry.fileURL, newDocURL<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Simple renaming to start</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a><span style="color: #002200;">*</span> fileManager <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span> error;
    <span style="color: #a61390;">BOOL</span> success <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>fileManager moveItemAtURL<span style="color: #002200;">:</span>entry.fileURL toURL<span style="color: #002200;">:</span>newDocURL error<span style="color: #002200;">:&amp;</span>error<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Failed to move file: %@&quot;</span>, error.localizedDescription<span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>    
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Fix up entry</span>
    entry.fileURL <span style="color: #002200;">=</span> newDocURL;
    <span style="color: #a61390;">int</span> index <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self indexOfEntryWithFileURL<span style="color: #002200;">:</span>entry.fileURL<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self.tableView reloadRowsAtIndexPaths<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> indexPathForRow<span style="color: #002200;">:</span>index inSection<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> withRowAnimation<span style="color: #002200;">:</span>UITableViewRowAnimationNone<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>This checks if the name is available (and warns the user if not), and otherwise moves the file using NSFileManager&#8217;s moveItemAtURL API.  This particular API has problems when it comes to iCloud (which we&#8217;ll discuss later) but works quite fine with local files so we&#8217;ll keep it that way.</p>
<p>Now let&#8217;s call this method when the user renames a file by modify the text field of a cell while in edit mode.  Remember how we added a delegate to the UITableViewCell to notify us when the user changes the text for the filename, but never implemented it?  Now&#8217;s the time!</p>
<p>Add the following code right above the &#8220;View lifecycle&#8221; section with awakeFromNib:</p>

<div class="wp_codebox"><table><tr id="p1279481"><td class="code" id="p12794code81"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#pragma mark Text Views</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>textChanged<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITextField <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>textField <span style="color: #002200;">&#123;</span>
    UIView <span style="color: #002200;">*</span> view <span style="color: #002200;">=</span> textField.superview;
    <span style="color: #a61390;">while</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>view isKindOfClass<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>PTKEntryCell class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span>
        view <span style="color: #002200;">=</span> view.superview;
    <span style="color: #002200;">&#125;</span>
    PTKEntryCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>PTKEntryCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> view;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span> indexPath <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self.tableView indexPathForCell<span style="color: #002200;">:</span>cell<span style="color: #002200;">&#93;</span>;
    PTKEntry <span style="color: #002200;">*</span> entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_objects objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Want to rename %@ to %@&quot;</span>, entry.description, textField.text<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#91;</span>self renameEntry<span style="color: #002200;">:</span>entry to<span style="color: #002200;">:</span>textField.text<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>textFieldShouldReturn<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITextField <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>textField <span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>textField resignFirstResponder<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self textChanged<span style="color: #002200;">:</span>textField<span style="color: #002200;">&#93;</span>;
	<span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Pretty simple, eh?  Compile and run, and now you can rename files!</p>
<h2>Bonus: Scrolling Fix</h2>
<p>If you have a lot of photos, you might notice that if you tap on a text field toward the bottom of the table view, the keybaord overlaps it so you can&#8217;t see what you&#8217;re editing.  That&#8217;s kind of annoying, eh?</p>
<p>Here&#8217;s a quick fix courtesy of <a href="http://stackoverflow.com/questions/594181/uitableview-and-keyboard-scrolling-issue">ZeLogolas on StackOverflow</a>.  Make the following changes to PTKMasterViewController.m:</p>

<div class="wp_codebox"><table><tr id="p1279482"><td class="code" id="p12794code82"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add private instance variable</span>
UITextField <span style="color: #002200;">*</span> _activeTextField;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add inside &quot;Text Views&quot; section, above textChanged</span>
<span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> keyboardWillShow<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span style="color: #400080;">NSNotification</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>note
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Get the keyboard size</span>
    CGRect keyboardBounds;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>note.userInfo valueForKey<span style="color: #002200;">:</span>UIKeyboardFrameBeginUserInfoKey<span style="color: #002200;">&#93;</span> getValue<span style="color: #002200;">:</span> <span style="color: #002200;">&amp;</span>keyboardBounds<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Detect orientation</span>
    UIInterfaceOrientation orientation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIApplication sharedApplication<span style="color: #002200;">&#93;</span> statusBarOrientation<span style="color: #002200;">&#93;</span>;
    CGRect frame <span style="color: #002200;">=</span> self.tableView.frame;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Start animation</span>
    <span style="color: #002200;">&#91;</span>UIView beginAnimations<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> context<span style="color: #002200;">:</span><span style="color: #a61390;">NULL</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView setAnimationBeginsFromCurrentState<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView setAnimationDuration<span style="color: #002200;">:</span>0.3f<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Reduce size of the Table view </span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>orientation <span style="color: #002200;">==</span> UIInterfaceOrientationPortrait || orientation <span style="color: #002200;">==</span> UIInterfaceOrientationPortraitUpsideDown<span style="color: #002200;">&#41;</span>
        frame.size.height <span style="color: #002200;">-=</span> keyboardBounds.size.height;
    <span style="color: #a61390;">else</span> 
        frame.size.height <span style="color: #002200;">-=</span> keyboardBounds.size.width;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Apply new size of table view</span>
    self.tableView.frame <span style="color: #002200;">=</span> frame;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Scroll the table view to see the TextField just above the keyboard</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_activeTextField<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        CGRect textFieldRect <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self.tableView convertRect<span style="color: #002200;">:</span>_activeTextField.superview.bounds fromView<span style="color: #002200;">:</span>_activeTextField.superview<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>self.tableView scrollRectToVisible<span style="color: #002200;">:</span>textFieldRect animated<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>UIView commitAnimations<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> keyboardWillHide<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span style="color: #400080;">NSNotification</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>note
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Get the keyboard size</span>
    CGRect keyboardBounds;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>note.userInfo valueForKey<span style="color: #002200;">:</span>UIKeyboardFrameBeginUserInfoKey<span style="color: #002200;">&#93;</span> getValue<span style="color: #002200;">:</span> <span style="color: #002200;">&amp;</span>keyboardBounds<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Detect orientation</span>
    UIInterfaceOrientation orientation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIApplication sharedApplication<span style="color: #002200;">&#93;</span> statusBarOrientation<span style="color: #002200;">&#93;</span>;
    CGRect frame <span style="color: #002200;">=</span> self.tableView.frame;
&nbsp;
    <span style="color: #002200;">&#91;</span>UIView beginAnimations<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> context<span style="color: #002200;">:</span><span style="color: #a61390;">NULL</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView setAnimationBeginsFromCurrentState<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView setAnimationDuration<span style="color: #002200;">:</span>0.3f<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Reduce size of the Table view </span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>orientation <span style="color: #002200;">==</span> UIInterfaceOrientationPortrait || orientation <span style="color: #002200;">==</span> UIInterfaceOrientationPortraitUpsideDown<span style="color: #002200;">&#41;</span>
        frame.size.height <span style="color: #002200;">+=</span> keyboardBounds.size.height;
    <span style="color: #a61390;">else</span> 
        frame.size.height <span style="color: #002200;">+=</span> keyboardBounds.size.width;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Apply new size of table view</span>
    self.tableView.frame <span style="color: #002200;">=</span> frame;
&nbsp;
    <span style="color: #002200;">&#91;</span>UIView commitAnimations<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>textFieldDidBeginEditing<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITextField <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>textField
<span style="color: #002200;">&#123;</span>
    _activeTextField <span style="color: #002200;">=</span> textField;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>textFieldDidEndEditing<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITextField <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>textField
<span style="color: #002200;">&#123;</span>
    _activeTextField <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add at bottom of viewDidLoad</span>
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>keyboardWillShow<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> name<span style="color: #002200;">:</span>UIKeyboardWillShowNotification object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>keyboardWillHide<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> name<span style="color: #002200;">:</span>UIKeyboardWillHideNotification object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add at bottom of viewDidUnload</span>
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> removeObserver<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Compile and run, and it will now auto-scroll if you select an item at the bottom!</p>
<h2>Where To Go From Here?</h2>
<p>Here is a download with the state of the <a href="http://d1xzuxjlafny7l.cloudfront.net/downloads/PhotoKeeper1.zip">code sample</a> so far.</p>
<p>At this point you have a fully functional UIDocument based app that stores documents locally.  You have now laid the groundwork that will make adding iCloud support much easier!</p>
<p>In the next part of the series, we&#8217;ll finally get to iCloud itself!  We&#8217;ll get the basics working, and then in the final part of the series we&#8217;ll cover more advanced aspects like moving files to/from iCloud, handling conflicts, and more.</p>
<p>If you have any questions, comments, or suggestions about better ways to do things, please join the forum discussion below!  :]</p>
<p><img src="http://d1xzuxjlafny7l.cloudfront.net/downloads/RayWenderlich.jpg" class="photo alignleft" /><br />
<i>This is a blog post by site administrator <a href="http://www.raywenderlich.com/about">Ray Wenderlich</a>, an independent software developer and gamer.</i></p>
<p><a href="http://www.raywenderlich.com/12794/icloud-and-uidocument-beyond-the-basics-part-2">iCloud and UIDocument: Beyond the Basics. Part 2/4</a> is a post from: <a href="http://www.raywenderlich.com">Ray Wenderlich</a></p>
<div id="tweetbutton12794" class="tw_button" style="float:left;"><a href="http://twitter.com/share?url=http%3A%2F%2Fbit.ly%2FJKLOWk&amp;via=rwenderlich&amp;text=iCloud%20and%20UIDocument%3A%20Beyond%20the%20Basics.%20Part%202%2F4&amp;related=rwenderlich&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fwww.raywenderlich.com%2F12794%2Ficloud-and-uidocument-beyond-the-basics-part-2" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://d1xzuxjlafny7l.cloudfront.net/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><img src="http://feeds.feedburner.com/~r/RayWenderlich/~4/Lj881StOveM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.raywenderlich.com/12794/icloud-and-uidocument-beyond-the-basics-part-2/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.raywenderlich.com/12794/icloud-and-uidocument-beyond-the-basics-part-2</feedburner:origLink></item>
		<item>
		<title>iCloud and UIDocument: Beyond the Basics. Part 1/4</title>
		<link>http://feedproxy.google.com/~r/RayWenderlich/~3/rNSp-snqkeg/icloud-and-uidocument-beyond-the-basics-part-1</link>
		<comments>http://www.raywenderlich.com/12779/icloud-and-uidocument-beyond-the-basics-part-1#comments</comments>
		<pubDate>Mon, 07 May 2012 15:00:59 +0000</pubDate>
		<dc:creator>Ray Wenderlich</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iCloud]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[ios5]]></category>
		<category><![CDATA[sample code]]></category>
		<category><![CDATA[storyboards]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[UIKit]]></category>

		<guid isPermaLink="false">http://www.raywenderlich.com/?p=12779</guid>
		<description><![CDATA[TweetThis is a blog post by site administrator Ray Wenderlich, an independent software developer and gamer. Creating a document-based iCloud [...]<p><a href="http://www.raywenderlich.com/12779/icloud-and-uidocument-beyond-the-basics-part-1">iCloud and UIDocument: Beyond the Basics. Part 1/4</a> is a post from: <a href="http://www.raywenderlich.com">Ray Wenderlich</a></p>
]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton12779" class="tw_button" style="float:left;"><a href="http://twitter.com/share?url=http%3A%2F%2Fbit.ly%2FIEoozq&amp;via=rwenderlich&amp;text=iCloud%20and%20UIDocument%3A%20Beyond%20the%20Basics.%20Part%201%2F4&amp;related=rwenderlich&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fwww.raywenderlich.com%2F12779%2Ficloud-and-uidocument-beyond-the-basics-part-1" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://d1xzuxjlafny7l.cloudfront.net/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><div id="attachment_12780" class="wp-caption alignright" style="width: 292px"><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/iCloudTutorial.jpg"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/iCloudTutorial-282x320.jpg" alt="Learn how to make a complete UIDocument + iCloud app!" title="Learn how to make a complete UIDocument + iCloud app!" width="282" height="320" class="size-medium wp-image-12780" /></a><p class="wp-caption-text">Learn how to make a complete UIDocument + iCloud app!</p></div>
<p><i>This is a blog post by site administrator <a href="http://www.raywenderlich.com/about">Ray Wenderlich</a>, an independent software developer and gamer.</i></p>
<p>Creating a document-based iCloud app is complicated.  There&#8217;s a lot of different things to think about, and it&#8217;s easy to forget to implement something out or make a mistake along the way.</p>
<p>There are several tutorials on creating iCloud apps out there, including Apple&#8217;s <a href="http://developer.apple.com/library/ios/#DOCUMENTATION/General/Conceptual/iCloud101/GettingStarted/GettingStarted.html">Your Third iOS App</a> tutorial and our own <a href="http://www.raywenderlich.com/store/ios-5-by-tutorials">iOS 5 by Tutorials</a>, which do a great job of explaining the basics of using iCloud.</p>
<p>What we really need is a tutorial that goes beyond the basics and puts everything together into a complete app that you (gasp) might actually be able to use.  This is my attempt to put something like that together for you guys!</p>
<p>In this tutorial, we&#8217;re going to create a simple iCloud document based app called PhotoKeeper.  It will show you how to do the following:</p>
<ul>
<li>Create, Read, Update, and Delete documents &#8211; both on iCloud *and* locally</li>
<li>Create documents consisting of multiple files with NSFileWrapper</li>
<li>Give previews of documents in the master view in an efficient manner</li>
<li>Allow a toggle for the user to enable/disable iCloud in Settings</li>
<li>Move/copy files to and from iCloud when user switches</li>
<li>Alllow renaming and deleting files &#8211; the safe way</li>
<li>Deal with conflicts and document updates</li>
</ul>
<p>This is a four part tutorial series.  In the first two parts we&#8217;ll get things working for local documents only, and then in the second two parts we&#8217;ll add iCloud support.  </p>
<p>Are you ready to see how to put everything together with iCloud?  Let&#8217;s get started!<span id="more-12779"></span><br />
<h2>Choosing our iCloud Storage Method</h2>
<p>In this tutorial, we are going to create a simple app called PhotoKeeper that allows users to store and name their favorite photos either locally or in iCloud.</p>
<p>There are three main ways an app can store its data in iCloud.  Which should we choose for this app?</p>
<ol>
<li><em>Use Key/Value Store.</em> iCloud has an extremely easy to use helper class called NSUbiquitousKeyValueStore that is very similar to NSUserDefaults.  If your app has a small amount of data to store (< 1 MB), this method is usually the best choice.</li>
<li><em>Use Core Data.</em> You can set up Core Data to store its data on iCloud.  If your app doesn&#8217;t have the concept of documents or files but has a large amount of data, this method is usually the best choice.</li>
<li><em>Create a Document-Based App.</em> The final method is to create a document based app by subclassing a class called UIDocument.  If your app is based around the concept of individual documents that the user can create/read/update/delete that you want listed as separate files in Settings, this method is usually the best choice.</li>
</ol>
<p>For PhotoKeeper, the third option makes the most sense.  We want each photo treated as a separate unit/document/file that we can see in iCloud storage separately.</p>
<p>If you think Key/Value Storage or iCloud makes more sense for your app, check out <a href="http://www.raywenderlich.com/store/ios-5-by-tutorials">iOS 5 by Tutorials</a>, where we have some examples and more details on those techniques.</p>
<h2>iCloud Document-Based App Overview</h2>
<p>Next let&#8217;s give an overview of what it takes to make an iCloud Document-Based App, and some design choices we&#8217;re going to make for PhotoKeeper along the way.  We will cover five topics:</p>
<ol>
<li>How it Works</li>
<li>Subclassing UIDocument</li>
<li>Input/Output Formats</li>
<li>Local vs. iCloud</li>
<li>Storage Philosophy</li>
</ol>
<p><em>1) How it Works</em></p>
<p>At a very high level, here&#8217;s how iCloud and UIDocument works.</p>
<p>If iCloud is available and your app is configured to use iCloud, your app can access a special directory on the device.  Whatever you put in this directory will be automatically synchronized to iCloud by a system daemon.</p>
<p>You can&#8217;t just enumerate this directory with normal APIs &#8211; you have to use a special API we&#8217;ll discuss later.  You also have to be careful about accessing files in this directory, because the the iCloud daemon is also working with the files at the same time.</p>
<p>The easiest way to work with these files is by subclassing a class called UIDocument.  It takes care most of the details for you (such as coordinating with the iCloud daemon and more), and allows you to focus primarily on what matters to you &#8211; your app&#8217;s data!</p>
<p>For more details on how iCloud works, check out the the <a href="http://developer.apple.com/library/ios/#DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/iCloud/iCloud.html">iOS App Programming Guide: iCloud Storage</a>.</p>
<div id="attachment_12787" class="wp-caption alignnone" style="width: 339px"><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/syncing_overview.jpg"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/syncing_overview.jpg" alt="Via Apple&#039;s iOS Programming Guide." title="Via Apple&#039;s iOS Programming Guide." width="329" height="378" class="size-full wp-image-12787" /></a><p class="wp-caption-text">Via Apple&#039;s iOS Programming Guide.</p></div>
<p><em>2) Subclassing UIDocument</em></p>
<p>When you subclass UIDocument you need to overrride two methods:</p>
<ul>
<li><em>loadFromContents:ofType:error:</em> Think of this as &#8220;read the document&#8221;.  You get an input class, and you have to decode it to your internal model.</li>
<li><em>contentsForType:error:</em> Think of this as &#8220;write the document&#8221;.  You encode your internal model to an output class.</li>
</ul>
<p>It&#8217;s usually best if your UIDocument class contains a reference to your app&#8217;s model class, which can be just a plain old NSObject.  If your model object supports NSCoding (tutorial here), implementing these methods is trivial.</p>
<p>For this tutorial, we&#8217;ve kept our document&#8217;s data model very simple &#8211; it&#8217;s literally jsut a photo!  However, you can use this same technique we&#8217;re demonstrating in this tutorial no matter how complex or large your docuemnt is.</p>
<p><em>3) Input/Output Formats</em></p>
<p>UIDocument supports two different classes for input/output: </p>
<ul>
<li><em>NSData.</em> This represents a simple buffer of data, which is good when your document is just a single file.
<li><em>NSFileWrapper.</em> This represents a directory of file packages, which the OS treats as a single file.  This is good for when your document consists of multiple files that you want to be able to load independently.</li>
</ul>
<p>At first glance, it might seem that using NSData would make the most sense, since our document is just a simple photo.</p>
<p>However, one of the design goals of PhotoKeeper is to show a thumbnail of the photo in the master view controller before the user opens a file.  If we used NSData, to get the thumbnails we&#8217;d have to open and decode every single document from the disk.  Since the images can be quite large, this could lead to slow performance and high memory overhead.</p>
<p>So what we&#8217;re going to do instead is use NSFileWrapper.  We&#8217;ll store two documents inside the wrapper:</p>
<ol>
<li><em>The main data.</em> This will be the main data of the document.  For PhotoKeeper, this will be our full size photo.</li>
<li><em>The metadata.</em> This will be anything the master view controller needs to display a preview.  It should be a small amount of data that can be loaded quickly.  For PhotoKeeper, this will be a small (resized) thumbnail of the photo.</li>
</ol>
<p>This way the master view controller only needs to load each photo&#8217;s (small) metadata sub-file inside the NSWrapper instead of the entire (large) data sub-file.  It might not make a huge difference in this tutorial, but the larger your document&#8217;s data file becomes the more useful this is!</p>
<p><em>4) Local vs. iCloud</em></p>
<p>It&#8217;s not enough to make an app that is just iCloud enabled &#8211; it also has to work without iCloud too!  </p>
<p>This is because the user might not have iCloud enabled on their device, or may want to turn iCloud off specifically for your app.</p>
<p>One of the nice things about using UIDocument is you can use it for both local storage and iCloud storage, so you don&#8217;t have to have two widely different code paths.</p>
<p>However, adding iCloud support with UIDocument does have a lot of extra steps and subtle problems to address.  So I personally find it easier to get your app working locally with UIDocument, and then adding iCloud support once that&#8217;s working.  So that&#8217;s what we&#8217;re going to do in this series!</p>
<p><em>5) Storage Philosophy</em></p>
<p>It is theoretically possible to design an app that has two different tabs &#8211; iCloud and local &#8211; and allow users to select where to store individual documents.</p>
<p>However, it appears this is not a philosphy Apple wants us to follow.  According to the <a href="https://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/DocumentBasedAppPGiOS/ManageDocumentLifeCycle/ManageDocumentLifeCycle.html#//apple_ref/doc/uid/TP40011149-CH4-SW8">Document-Based App Programming Guide for iOS</a>:</p>
<div class="note">
<p><i>All documents of an application are stored either in the local sandbox or in an iCloud container directory. A user should not be able to select individual documents for storage in iCloud.</i></p>
</div>
<p>The same document also recommends that users have an option to disable iCloud for your app.  I think the best place for this is in Settings, since it&#8217;s a setting that only needs to be changed rarely, reduces the clutter in your app, and discourages users from messing with it once they have it set up.</p>
<h2>Putting it All Together</h2>
<p>Phew &#8211; that&#8217;s a lot of background information!  Don&#8217;t worry if you don&#8217;t understand everything right away, it will become more clear as we work through the tutorial.</p>
<p>To sum up what we discussed above, we will be doing the following for PhotoKeeper:</p>
<ul>
<li>Choosing a Document-Based App as our storage method.</li>
<li>Creating a model class (a plain old NSObject that stores our large photo) that implements NSCoding.</li>
<li>Creating a metadata class (a plain old NSObject that stores our small thumbnail) that implements NSCoding.</li>
<li>Subclassing UIDocument.  It will have a reference to the model and metadata classes.</li>
<li>Using NSFileWrapper for input/output.  Our UIDocumentClass will encode both the model and metadata into separate files inside our NSFileWrapper directory.</li>
<li>Work both locally and for iCloud.  We will start with local only and add iCloud support later in the series.</li>
<li>Add iCloud on/off toggle in Settings.  All documents will be stored either locally or in iCloud.</li>
</ul>
<p>Note that for your apps you might make different design decisions than the above &#8211; however if you&#8217;re UIDocument based most of this tutorial will still apply, so read on :]</p>
<h2>Getting Started</h2>
<p>It&#8217;s finally time to code!</p>
<p>Create a new project in Xcode and choose the iOS\Application\Master-Detail Application tepmlate.  Enter PhotoKeeper for product name, PTK as the Class Prefix, select iPhone for the Device Family, and make sure Use Storyboards and Use Automatic Reference Counting are checked (but nothing else).</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/CreateProject.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/CreateProject-700x473.png" alt="Creating a new project in Xcode" title="Creating a new project in Xcode" width="700" height="473" class="alignnone size-large wp-image-12788" /></a></p>
<p>Next, download the <a href="http://d1xzuxjlafny7l.cloudfront.net/downloads/PhotoKeeperResources.zip">resources for this project</a> and add them to your Xcode project.  These are just two simple classes to help format a string or resize images and a few images &#8211; take a peek if you want.</p>
<p>Compile and run the project, and you&#8217;ll see the template has generated a skeleton of a simple master/detail app.  You can tap the + button to add entries, and tap an entry to go to a detail screen.</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/MasterDetailTemplate.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/MasterDetailTemplate.png" alt="The Master/Detail template in Xcode" title="The Master/Detail template in Xcode" width="680" height="500" class="alignnone size-full wp-image-12789" /></a></p>
<p>Our goal in this first part of the series is to switch the master view to showing a list of local UIDocuments, and allow the + button to create a new UIDocument.</p>
<p>Before we can create a UIDocuemnt subclass though, we need to create our model classes.  </p>
<p>Let&#8217;s start with the main model class.  Create a new file with the iOS\Cocoa Touch\Objective-C class template, name it PTKData, and make it a subclass of NSObject.  Then replace the contents of PTKData.h with the following:</p>

<div class="wp_codebox"><table><tr id="p12779103"><td class="code" id="p12779code103"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;Foundation/Foundation.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> PTKData <span style="color: #002200;">:</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> &lt;NSCoding&gt;
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong<span style="color: #002200;">&#41;</span> UIImage <span style="color: #002200;">*</span> photo;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>And replace PTKData.m with the following:</p>

<div class="wp_codebox"><table><tr id="p12779104"><td class="code" id="p12779code104"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;PTKData.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> PTKData
<span style="color: #a61390;">@synthesize</span> photo <span style="color: #002200;">=</span> _photo;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithPhoto<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>photo <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        self.photo <span style="color: #002200;">=</span> photo;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>init <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self initWithPhoto<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark NSCoding</span>
&nbsp;
<span style="color: #6e371a;">#define kVersionKey @&quot;Version&quot;</span>
<span style="color: #6e371a;">#define kPhotoKey @&quot;Photo&quot;</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>encodeWithCoder<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSCoder_Class/"><span style="color: #400080;">NSCoder</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>encoder <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>encoder encodeInt<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span> forKey<span style="color: #002200;">:</span>kVersionKey<span style="color: #002200;">&#93;</span>;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/"><span style="color: #400080;">NSData</span></a> <span style="color: #002200;">*</span> photoData <span style="color: #002200;">=</span> UIImagePNGRepresentation<span style="color: #002200;">&#40;</span>self.photo<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#91;</span>encoder encodeObject<span style="color: #002200;">:</span>photoData forKey<span style="color: #002200;">:</span>kPhotoKey<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithCoder<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSCoder_Class/"><span style="color: #400080;">NSCoder</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>decoder <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>decoder decodeIntForKey<span style="color: #002200;">:</span>kVersionKey<span style="color: #002200;">&#93;</span>;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/"><span style="color: #400080;">NSData</span></a> <span style="color: #002200;">*</span> photoData <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>decoder decodeObjectForKey<span style="color: #002200;">:</span>kPhotoKey<span style="color: #002200;">&#93;</span>;
    UIImage <span style="color: #002200;">*</span> photo <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIImage imageWithData<span style="color: #002200;">:</span>photoData<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self initWithPhoto<span style="color: #002200;">:</span>photo<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>As you can see, this is a very simple model class that only has one piece of data to track &#8211; the full size photo.  It implements the NSCoding protocol to encode/decode to a buffer of data.  </p>
<p>Note that it stores a version number along with the photo.  This makes it easy to update the data structure if you want to in the future while still supporting older files.  If you ever add a new field, you bump up the version number, then while decoding you can check the version number to see if the new field is available.</p>
<p>For more information on NSCoding, check out <a href="http://www.raywenderlich.com/1914/how-to-save-your-app-data-with-nscoding-and-nsfilemanager">this tutorial</a>.</p>
<p>Next, let&#8217;s create the metadata model class.  Again, the purpose of this class is so we can store a much smaller thumbnail version of the photo that will load quickly in the master view controller.</p>
<p>Create a new file with the iOS\Cocoa Touch\Objective-C class template, name it PTKMetadata, and make it a subclass of NSObject.  Then replace the contents of PTKMetadata.h with the following:</p>

<div class="wp_codebox"><table><tr id="p12779105"><td class="code" id="p12779code105"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;Foundation/Foundation.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> PTKMetadata <span style="color: #002200;">:</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> &lt;NSCoding&gt;
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong<span style="color: #002200;">&#41;</span> UIImage <span style="color: #002200;">*</span> thumbnail;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>And replace PTKMetadata.m with the following:</p>

<div class="wp_codebox"><table><tr id="p12779106"><td class="code" id="p12779code106"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;PTKMetadata.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> PTKMetadata
<span style="color: #a61390;">@synthesize</span> thumbnail <span style="color: #002200;">=</span> _thumbnail;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithThumbnail<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>thumbnail <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        self.thumbnail <span style="color: #002200;">=</span> thumbnail;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>init <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self initWithThumbnail<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark NSCoding</span>
&nbsp;
<span style="color: #6e371a;">#define kVersionKey @&quot;Version&quot;</span>
<span style="color: #6e371a;">#define kThumbnailKey @&quot;Thumbnail&quot;</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>encodeWithCoder<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSCoder_Class/"><span style="color: #400080;">NSCoder</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>encoder <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>encoder encodeInt<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span> forKey<span style="color: #002200;">:</span>kVersionKey<span style="color: #002200;">&#93;</span>;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/"><span style="color: #400080;">NSData</span></a> <span style="color: #002200;">*</span> thumbnailData <span style="color: #002200;">=</span> UIImagePNGRepresentation<span style="color: #002200;">&#40;</span>self.thumbnail<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#91;</span>encoder encodeObject<span style="color: #002200;">:</span>thumbnailData forKey<span style="color: #002200;">:</span>kThumbnailKey<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithCoder<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSCoder_Class/"><span style="color: #400080;">NSCoder</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>decoder <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>decoder decodeIntForKey<span style="color: #002200;">:</span>kVersionKey<span style="color: #002200;">&#93;</span>;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/"><span style="color: #400080;">NSData</span></a> <span style="color: #002200;">*</span> thumbnailData <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>decoder decodeObjectForKey<span style="color: #002200;">:</span>kThumbnailKey<span style="color: #002200;">&#93;</span>;
    UIImage <span style="color: #002200;">*</span> thumbnail <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIImage imageWithData<span style="color: #002200;">:</span>thumbnailData<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self initWithThumbnail<span style="color: #002200;">:</span>thumbnail<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>This is pretty much exactly the same as PTKData, so no need to discuss further here.  We even could have used the same class, but it&#8217;s better to keep things separate in case we need more data fields in the future (which will be the case for most apps).</p>
<p>Congrats &#8211; now you have the model classes for PhotoKeeper!</p>
<h2>Subclassing UIDocument</h2>
<p>Next we are going to create a subclass of UIDocument that will combine the data and metadata into a single NSFileWrapper.</p>
<p>Create a new file with the iOS\Cocoa Touch\Objective-C class template, name it PTKDocument, and make it a subclass of UIDocument.  Then replace the contents of PTKDocument.h with the following:</p>

<div class="wp_codebox"><table><tr id="p12779107"><td class="code" id="p12779code107"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;UIKit/UIKit.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@class</span> PTKData;
<span style="color: #a61390;">@class</span> PTKMetadata;
&nbsp;
<span style="color: #6e371a;">#define PTK_EXTENSION @&quot;ptk&quot;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> PTKDocument <span style="color: #002200;">:</span> UIDocument
&nbsp;
<span style="color: #11740a; font-style: italic;">// Data</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>photo;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setPhoto<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>photo;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Metadata</span>
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, strong<span style="color: #002200;">&#41;</span> PTKMetadata <span style="color: #002200;">*</span> metadata;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> description;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Even though NSFileWrapper is basically a directory, we still need to give it a file extension so we can identify the directory as a document our app knows how to handle.  We&#8217;ll use &#8220;ptk&#8221; as our file extension, so we define it here for easy access later.</p>
<p>Rather than letting users of PTKDocument access the PTKData directly, it&#8217;s best if you add accessors instead.  This is because UIDocument is built around the concept of undo/redo &#8211; it has an undo manager and when you make changes UIDocument can auto-save in the background.  Accessors are the perfect spot to register your undo actions, which you&#8217;ll see in a minute.</p>
<p>It&#8217;s OK if the user accesses the metadata directly though, as it&#8217;s not something the app will modify.  Instead, the metadata will be automatically updated when the user sets the photo.</p>
<p>Next open PTKDocument.m.  There&#8217;s a lot of code we&#8217;re going to add here, so let&#8217;s go over it bit by bit.</p>

<div class="wp_codebox"><table><tr id="p12779108"><td class="code" id="p12779code108"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;PTKDocument.h&quot;</span>
<span style="color: #6e371a;">#import &quot;PTKData.h&quot;</span>
<span style="color: #6e371a;">#import &quot;PTKMetadata.h&quot;</span>
<span style="color: #6e371a;">#import &quot;UIImageExtras.h&quot;</span>
&nbsp;
<span style="color: #6e371a;">#define METADATA_FILENAME   @&quot;photo.metadata&quot;</span>
<span style="color: #6e371a;">#define DATA_FILENAME       @&quot;photo.data&quot;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> PTKDocument <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, strong<span style="color: #002200;">&#41;</span> PTKData <span style="color: #002200;">*</span> data;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, strong<span style="color: #002200;">&#41;</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSFileWrapper_Class/"><span style="color: #400080;">NSFileWrapper</span></a> <span style="color: #002200;">*</span> fileWrapper;
<span style="color: #a61390;">@end</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> PTKDocument 
<span style="color: #a61390;">@synthesize</span> data <span style="color: #002200;">=</span> _data;
<span style="color: #a61390;">@synthesize</span> fileWrapper <span style="color: #002200;">=</span> _fileWrapper;
<span style="color: #a61390;">@synthesize</span> metadata <span style="color: #002200;">=</span> _metadata;</pre></td></tr></table></div>

<p>First we import the headers we need and define the filenames for the two sub-files that will be inside our directory/NSFileWrapper.</p>
<p>Then we create two private properties &#8211; one for the main document model class (PTKData), and one for the NSFileWrapper (the class that treats the directory as a single file).  Finally we synthseize our properties.</p>
<p>Next add the code to write the UIDocument to disk:</p>

<div class="wp_codebox"><table><tr id="p12779109"><td class="code" id="p12779code109"><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>encodeObject<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>id&lt;NSCoding&gt;<span style="color: #002200;">&#41;</span>object toWrappers<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/"><span style="color: #400080;">NSMutableDictionary</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>wrappers preferredFilename<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>preferredFilename <span style="color: #002200;">&#123;</span>
    @autoreleasepool <span style="color: #002200;">&#123;</span>            
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableData_Class/"><span style="color: #400080;">NSMutableData</span></a> <span style="color: #002200;">*</span> data <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableData_Class/"><span style="color: #400080;">NSMutableData</span></a> data<span style="color: #002200;">&#93;</span>;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSKeyedArchiver_Class/"><span style="color: #400080;">NSKeyedArchiver</span></a> <span style="color: #002200;">*</span> archiver <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSKeyedArchiver_Class/"><span style="color: #400080;">NSKeyedArchiver</span></a> alloc<span style="color: #002200;">&#93;</span> initForWritingWithMutableData<span style="color: #002200;">:</span>data<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>archiver encodeObject<span style="color: #002200;">:</span>object forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;data&quot;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>archiver finishEncoding<span style="color: #002200;">&#93;</span>;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSFileWrapper_Class/"><span style="color: #400080;">NSFileWrapper</span></a> <span style="color: #002200;">*</span> wrapper <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSFileWrapper_Class/"><span style="color: #400080;">NSFileWrapper</span></a> alloc<span style="color: #002200;">&#93;</span> initRegularFileWithContents<span style="color: #002200;">:</span>data<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>wrappers setObject<span style="color: #002200;">:</span>wrapper forKey<span style="color: #002200;">:</span>preferredFilename<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>contentsForType<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>typeName error<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span>__autoreleasing <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>outError <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>self.metadata <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span> || self.data <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>        
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;    
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/"><span style="color: #400080;">NSMutableDictionary</span></a> <span style="color: #002200;">*</span> wrappers <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/"><span style="color: #400080;">NSMutableDictionary</span></a> dictionary<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self encodeObject<span style="color: #002200;">:</span>self.metadata toWrappers<span style="color: #002200;">:</span>wrappers preferredFilename<span style="color: #002200;">:</span>METADATA_FILENAME<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self encodeObject<span style="color: #002200;">:</span>self.data toWrappers<span style="color: #002200;">:</span>wrappers preferredFilename<span style="color: #002200;">:</span>DATA_FILENAME<span style="color: #002200;">&#93;</span>;   
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSFileWrapper_Class/"><span style="color: #400080;">NSFileWrapper</span></a> <span style="color: #002200;">*</span> fileWrapper <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSFileWrapper_Class/"><span style="color: #400080;">NSFileWrapper</span></a> alloc<span style="color: #002200;">&#93;</span> initDirectoryWithFileWrappers<span style="color: #002200;">:</span>wrappers<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> fileWrapper;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Take a look at contentsForType first.  To create a directory NSFileWrapper, you call initDirectoryWithFileWrapper and pass in a dictionary that contains file NSFileWrappers as the objects, and the names of the files as the key.  We use a helper method encodeObject:toWrappers:preferredFilename to create a file NSFileWrapper for the data and metadata.</p>
<p>The encodeObject:toWrappers:preferredFilename method will look familiar if you are have used NSCoding in the past.  It uses the NSKeyedArchiver class to convert the object that implements NSCoding into a data buffer.  Then it creates a file NSFileWrapper with the buffer and adds it to the dictionary.</p>
<p>Sweet!  Now let&#8217;s implement reading.  Add the following to the file next:</p>

<div class="wp_codebox"><table><tr id="p12779110"><td class="code" id="p12779code110"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>decodeObjectFromWrapperWithPreferredFilename<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>preferredFilename <span style="color: #002200;">&#123;</span>
&nbsp;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSFileWrapper_Class/"><span style="color: #400080;">NSFileWrapper</span></a> <span style="color: #002200;">*</span> fileWrapper <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self.fileWrapper.fileWrappers objectForKey<span style="color: #002200;">:</span>preferredFilename<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>fileWrapper<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unexpected error: Couldn't find %@ in file wrapper!&quot;</span>, preferredFilename<span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/"><span style="color: #400080;">NSData</span></a> <span style="color: #002200;">*</span> data <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>fileWrapper regularFileContents<span style="color: #002200;">&#93;</span>;    
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSKeyedUnarchiver_Class/"><span style="color: #400080;">NSKeyedUnarchiver</span></a> <span style="color: #002200;">*</span> unarchiver <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSKeyedUnarchiver_Class/"><span style="color: #400080;">NSKeyedUnarchiver</span></a> alloc<span style="color: #002200;">&#93;</span> initForReadingWithData<span style="color: #002200;">:</span>data<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>unarchiver decodeObjectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;data&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>PTKMetadata <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>metadata <span style="color: #002200;">&#123;</span>    
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_metadata <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</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>self.fileWrapper <span style="color: #002200;">!=</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #11740a; font-style: italic;">//NSLog(@&quot;Loading metadata for %@...&quot;, self.fileURL);</span>
            self.metadata <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self decodeObjectFromWrapperWithPreferredFilename<span style="color: #002200;">:</span>METADATA_FILENAME<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
            self.metadata <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PTKMetadata alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>    
    <span style="color: #a61390;">return</span> _metadata;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>PTKData <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>data <span style="color: #002200;">&#123;</span>    
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_data <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</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>self.fileWrapper <span style="color: #002200;">!=</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #11740a; font-style: italic;">//NSLog(@&quot;Loading photo for %@...&quot;, self.fileURL);</span>
            self.data <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self decodeObjectFromWrapperWithPreferredFilename<span style="color: #002200;">:</span>DATA_FILENAME<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
            self.data <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PTKData alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>    
    <span style="color: #a61390;">return</span> _data;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>loadFromContents<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>contents ofType<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>typeName error<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span>__autoreleasing <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>outError <span style="color: #002200;">&#123;</span>
&nbsp;
    self.fileWrapper <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSFileWrapper_Class/"><span style="color: #400080;">NSFileWrapper</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> contents;    
&nbsp;
    <span style="color: #11740a; font-style: italic;">// The rest will be lazy loaded...</span>
    self.data <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    self.metadata <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Start at the bottom with loadFromContents:ofType:error:.  Notice how all we do is squirrel the passed in contents (a directory NSFileWrapper, since that&#8217;s what we saved) into a property.  We don&#8217;t actually load the data right away (although you can do that for your app if you want), since for this app we want to lazy load instead.</p>
<p>Lazy loading is a fancy way of saying &#8220;don&#8217;t load it until I ask for it.&#8221;  This is good for our app because the master view controller only needs to load the metadata.  The full data is only needed when you go to the detail view controller.</p>
<p>If you look at the accessors for metadata and data, they check to see if there is a directory NSFileWrapper stored, and if there is they read the appropriate file from the directory NSFileWrapper.  </p>
<p>Finally, decodeObjectFromWrapperWithPreferredFilename does the opposite of encodeObject:toWrappers:preferredFilename.  It reads the appropriate file NSFileWrapper from the directory NSFileWrapper and converts the NSData contents back to an object via the NSCoding protocol.</p>
<p>Almost done!  Just add this to the bottom of the file:</p>

<div class="wp_codebox"><table><tr id="p12779111"><td class="code" id="p12779code111"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> description <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self.fileURL lastPathComponent<span style="color: #002200;">&#93;</span> stringByDeletingPathExtension<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark Accessors</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>photo <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> self.data.photo;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setPhoto<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>photo <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self.data.photo isEqual<span style="color: #002200;">:</span>photo<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span>;
&nbsp;
    UIImage <span style="color: #002200;">*</span> oldPhoto <span style="color: #002200;">=</span> self.data.photo;
    self.data.photo <span style="color: #002200;">=</span> photo;
    self.metadata.thumbnail <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self.data.photo imageByScalingAndCroppingForSize<span style="color: #002200;">:</span>CGSizeMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">145</span>, <span style="color: #2400d9;">145</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>self.undoManager setActionName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Image Change&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self.undoManager registerUndoWithTarget<span style="color: #002200;">:</span>self selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>setPhoto<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> object<span style="color: #002200;">:</span>oldPhoto<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Description returns the filename without the path or extension, and photo is a simple getter.</p>
<p>The important part is setPhoto.  Not only does this set the photo in the data, but this also creates a smaller thumbnail image and saves it in the metadata.  </p>
<p>It also registers an undo action so that the user can undo the change (via shaking on the iPhone, or you can add a custom button).  By doing this, internally UIDocument now knows that the document has been modified, so it will auto-save periodically in the background.</p>
<p>w00t &#8211; now you have both the data model and UIDocument working!  Now it&#8217;s time to retrofit our master view controller to use it.</p>
<h2>Creating Documents</h2>
<p>Before we can display a list of documents, we need to have the ability to add at least one so we have something to look at.  So let&#8217;s start by imiplementing creating a new document.</p>
<p>There are four things you need to do in order to create a new document in this app:</p>
<ol>
<li>Store Entries</li>
<li>Find an Available URL</li>
<li>Create the Document</li>
<li>Make Final Changes</li>
</ol>
<p>Let&#8217;s go over these one by one!</p>
<p><em>Storing Entries</em></p>
<p>If you look at PTKMasterViewController.m, you&#8217;ll see that viewDidLoad adds a button to the toolbar that the user can tap to create a new entry:</p>

<div class="wp_codebox"><table><tr id="p12779112"><td class="code" id="p12779code112"><pre class="objc" style="font-family:monospace;">UIBarButtonItem <span style="color: #002200;">*</span>addButton <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIBarButtonItem alloc<span style="color: #002200;">&#93;</span> initWithBarButtonSystemItem<span style="color: #002200;">:</span>UIBarButtonSystemItemAdd target<span style="color: #002200;">:</span>self action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>insertNewObject<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
self.navigationItem.rightBarButtonItem <span style="color: #002200;">=</span> addButton;</pre></td></tr></table></div>

<p>When the button is tapped, insertNewObject is called.  The current implementation puts an NSDate in an array, which is displayed in a table view.</p>
<p>Instead of displaying NSDates, we want to display information about our documents.  For each document, we&#8217;ll need to know its file URL, its metadata (thumbnail), the date it was last modified, and what state the document is in (more on this later).</p>
<p>To keep track of all of this information we need, let&#8217;s create a new class real quick.  Create a new file with the iOS\Cocoa Touch\Objective-C class template, name it PTKEntry, and make it a subclass of NSObject.  Then replace the contents of PTKEntry.h with the following:</p>

<div class="wp_codebox"><table><tr id="p12779113"><td class="code" id="p12779code113"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;Foundation/Foundation.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@class</span> PTKMetadata;
&nbsp;
<span style="color: #a61390;">@interface</span> PTKEntry <span style="color: #002200;">:</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a>
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong<span style="color: #002200;">&#41;</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> fileURL;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong<span style="color: #002200;">&#41;</span> PTKMetadata <span style="color: #002200;">*</span> metadata;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>assign<span style="color: #002200;">&#41;</span> UIDocumentState state;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong<span style="color: #002200;">&#41;</span> NSFileVersion <span style="color: #002200;">*</span> version;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithFileURL<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>fileURL metadata<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>PTKMetadata <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>metadata state<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIDocumentState<span style="color: #002200;">&#41;</span>state version<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSFileVersion <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>version;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> description;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>This is a very simple class that just keeps track of all of the items we just discussed.  </p>
<p>Next switch to PTKEntry.m and add the implementation, which is simple as well:</p>

<div class="wp_codebox"><table><tr id="p12779114"><td class="code" id="p12779code114"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;PTKEntry.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> PTKEntry
&nbsp;
<span style="color: #a61390;">@synthesize</span> fileURL <span style="color: #002200;">=</span> _fileURL;
<span style="color: #a61390;">@synthesize</span> metadata <span style="color: #002200;">=</span> _metadata;
<span style="color: #a61390;">@synthesize</span> state <span style="color: #002200;">=</span> _state;
<span style="color: #a61390;">@synthesize</span> version <span style="color: #002200;">=</span> _version;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithFileURL<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>fileURL metadata<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>PTKMetadata <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>metadata state<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIDocumentState<span style="color: #002200;">&#41;</span>state version<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSFileVersion <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>version <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        self.fileURL <span style="color: #002200;">=</span> fileURL;
        self.metadata <span style="color: #002200;">=</span> metadata;
        self.state <span style="color: #002200;">=</span> state;
        self.version <span style="color: #002200;">=</span> version;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> self;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> description <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self.fileURL lastPathComponent<span style="color: #002200;">&#93;</span> stringByDeletingPathExtension<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p><em>Finding an Available URL</em></p>
<p>The next step is to figure out the full URL for where we want to create the document.  This isn&#8217;t as easy as it sounds, because we need to auto-generate a filename that isn&#8217;t already used.  And the first step of doing that is having a way to check if a file exists.</p>
<p>To help solve this, let&#8217;s assume that the _objects array contains all the PTKEntries on the disk.  Then all we have to do is look through this array to see if the name is already taken.</p>
<p>Let&#8217;s see what this looks like in code.  Make the following changes to PTKMasterViewController.m:</p>

<div class="wp_codebox"><table><tr id="p12779115"><td class="code" id="p12779code115"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add imports to top of file</span>
<span style="color: #6e371a;">#import &quot;PTKDocument.h&quot;</span>
<span style="color: #6e371a;">#import &quot;NSDate+FormattedStrings.h&quot;</span>
<span style="color: #6e371a;">#import &quot;PTKEntry.h&quot;</span>
<span style="color: #6e371a;">#import &quot;PTKMetadata.h&quot;'</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add new private variables to interface</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> _localRoot;
PTKDocument <span style="color: #002200;">*</span> _selDocument;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Add new methods right after @implementation</span>
<span style="color: #6e371a;">#pragma mark Helpers</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>iCloudOn <span style="color: #002200;">&#123;</span>    
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>localRoot <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_localRoot <span style="color: #002200;">!=</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> _localRoot;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span> paths <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> defaultManager<span style="color: #002200;">&#93;</span> URLsForDirectory<span style="color: #002200;">:</span>NSDocumentDirectory inDomains<span style="color: #002200;">:</span>NSUserDomainMask<span style="color: #002200;">&#93;</span>;
    _localRoot <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>paths objectAtIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> _localRoot;    
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>getDocURL<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>filename <span style="color: #002200;">&#123;</span>    
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self iCloudOn<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>        
        <span style="color: #11740a; font-style: italic;">// TODO</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self.localRoot URLByAppendingPathComponent<span style="color: #002200;">:</span>filename<span style="color: #002200;">&#93;</span>;    
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>docNameExistsInObjects<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>docName <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">BOOL</span> nameExists <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>PTKEntry <span style="color: #002200;">*</span> entry <span style="color: #a61390;">in</span> _objects<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>entry.fileURL lastPathComponent<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span>docName<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            nameExists <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
            <span style="color: #a61390;">break</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> nameExists;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Let&#8217;s start from the top.  We start by adding some imports we need, and add instance variables to keep track of the local root (i.e. the Documents directory) and the selected document when a user taps a row.  We also define a method to return whether iCloud is on or off.  For now we set it to always off, but we&#8217;ll come back to this later.</p>
<p>Next we write a getter for localRoot so it can be lazy loaded.  If it isn&#8217;t set yet, we use find the URL for the documents directory and squirrel it away in the instance variable.</p>
<p>getDocURL is a method where you pass in a filename and get the full path to the file.  If iCloud is off, this simply appends the filename to the Documents directory path.  We&#8217;ll add the iCloud implementation later.</p>
<p>Finally, docNameExistsInObjects loops through the list of PTKEntry instances in _objects and checks to see if the name matches any of them.  If it does, there&#8217;s a conflict, otherwise it&#8217;s OK.</p>
<p>Next add this method to find a non-taken name for a file:</p>

<div class="wp_codebox"><table><tr id="p12779116"><td class="code" id="p12779code116"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>getDocFilename<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>prefix uniqueInObjects<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>uniqueInObjects <span style="color: #002200;">&#123;</span>
    NSInteger docCount <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a><span style="color: #002200;">*</span> newDocName <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// At this point, the document list should be up-to-date.</span>
    <span style="color: #a61390;">BOOL</span> done <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #a61390;">BOOL</span> first <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
    <span style="color: #a61390;">while</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>done<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>first<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            first <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
            newDocName <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@.%@&quot;</span>,
                          prefix, PTK_EXTENSION<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
            newDocName <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@ %d.%@&quot;</span>,
                          prefix, docCount, PTK_EXTENSION<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Look for an existing document with the same name. If one is</span>
        <span style="color: #11740a; font-style: italic;">// found, increment the docCount value and try again.</span>
        <span style="color: #a61390;">BOOL</span> nameExists;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>uniqueInObjects<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            nameExists <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self docNameExistsInObjects<span style="color: #002200;">:</span>newDocName<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: #11740a; font-style: italic;">// TODO</span>
            <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
        <span style="color: #002200;">&#125;</span>
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>nameExists<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>            
            <span style="color: #a61390;">break</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
            docCount<span style="color: #002200;">++</span>;            
        <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> newDocName;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>This starts with the document name passed in and checks if it is available.  If not, it adds 1 to the end of the name and tries again.  If that fails it keeps incrementing the number until it finds an available name.</p>
<p><em>Creating a Document</em></p>
<p>To create a PTKDocument, there are two steps:</p>
<ol>
<li>Alloc/init the PTKDocument with the URL to save the file to.
<li>Call saveToURL to initially create the file.
</ol>
<p>After you call saveToURL, the document is effectively &#8220;opened&#8221; and in a usable state.</p>
<p>After we create the document, we need to update the objects array to store the document, and display the detail view controller.</p>
<p>Let&#8217;s add the code!  First we need to add a helper method to add (or update) a PTKEntry in the _objects array.  Add the following code right before awakeFromNib:</p>

<div class="wp_codebox"><table><tr id="p12779117"><td class="code" id="p12779code117"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#pragma mark Entry management methods</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>indexOfEntryWithFileURL<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>fileURL <span style="color: #002200;">&#123;</span>
    __block <span style="color: #a61390;">int</span> retval <span style="color: #002200;">=</span> <span style="color: #002200;">-</span><span style="color: #2400d9;">1</span>;
    <span style="color: #002200;">&#91;</span>_objects enumerateObjectsUsingBlock<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span>PTKEntry <span style="color: #002200;">*</span> entry, NSUInteger idx, <span style="color: #a61390;">BOOL</span> <span style="color: #002200;">*</span>stop<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>entry.fileURL isEqual<span style="color: #002200;">:</span>fileURL<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            retval <span style="color: #002200;">=</span> idx;
            <span style="color: #002200;">*</span>stop <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> retval;    
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>addOrUpdateEntryWithURL<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>fileURL metadata<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>PTKMetadata <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>metadata state<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIDocumentState<span style="color: #002200;">&#41;</span>state version<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSFileVersion <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>version <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #a61390;">int</span> index <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self indexOfEntryWithFileURL<span style="color: #002200;">:</span>fileURL<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Not found, so add</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>index <span style="color: #002200;">==</span> <span style="color: #002200;">-</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>    
&nbsp;
        PTKEntry <span style="color: #002200;">*</span> entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PTKEntry alloc<span style="color: #002200;">&#93;</span> initWithFileURL<span style="color: #002200;">:</span>fileURL metadata<span style="color: #002200;">:</span>metadata state<span style="color: #002200;">:</span>state version<span style="color: #002200;">:</span>version<span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #002200;">&#91;</span>_objects addObject<span style="color: #002200;">:</span>entry<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>self.tableView insertRowsAtIndexPaths<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> indexPathForRow<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>_objects.count <span style="color: #002200;">-</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span> inSection<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> withRowAnimation<span style="color: #002200;">:</span>UITableViewRowAnimationRight<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span> 
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Found, so edit</span>
    <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        PTKEntry <span style="color: #002200;">*</span> entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_objects objectAtIndex<span style="color: #002200;">:</span>index<span style="color: #002200;">&#93;</span>;
        entry.metadata <span style="color: #002200;">=</span> metadata;    
        entry.state <span style="color: #002200;">=</span> state;
        entry.version <span style="color: #002200;">=</span> version;
&nbsp;
        <span style="color: #002200;">&#91;</span>self.tableView reloadRowsAtIndexPaths<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> indexPathForRow<span style="color: #002200;">:</span>index inSection<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> withRowAnimation<span style="color: #002200;">:</span>UITableViewRowAnimationNone<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark View lifecycle</span></pre></td></tr></table></div>

<p>This is fairly simple so just take a look through, no need to discuss much here.</p>
<p>Next replace the implementation of insertNewObject with the following:</p>

<div class="wp_codebox"><table><tr id="p12779118"><td class="code" id="p12779code118"><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>insertNewObject<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;">// Determine a unique filename to create</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> fileURL <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self getDocURL<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self getDocFilename<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Photo&quot;</span> uniqueInObjects<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Want to create file at %@&quot;</span>, fileURL<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Create new document and save to the filename</span>
    PTKDocument <span style="color: #002200;">*</span> doc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PTKDocument alloc<span style="color: #002200;">&#93;</span> initWithFileURL<span style="color: #002200;">:</span>fileURL<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>doc saveToURL<span style="color: #002200;">:</span>fileURL forSaveOperation<span style="color: #002200;">:</span>UIDocumentSaveForCreating completionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Failed to create file at %@&quot;</span>, fileURL<span style="color: #002200;">&#41;</span>;
            <span style="color: #a61390;">return</span>;
        <span style="color: #002200;">&#125;</span> 
&nbsp;
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;File created at %@&quot;</span>, fileURL<span style="color: #002200;">&#41;</span>;        
        PTKMetadata <span style="color: #002200;">*</span> metadata <span style="color: #002200;">=</span> doc.metadata;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> fileURL <span style="color: #002200;">=</span> doc.fileURL;
        UIDocumentState state <span style="color: #002200;">=</span> doc.documentState;
        NSFileVersion <span style="color: #002200;">*</span> version <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSFileVersion currentVersionOfItemAtURL<span style="color: #002200;">:</span>fileURL<span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Add on the main thread and perform the segue</span>
        _selDocument <span style="color: #002200;">=</span> doc;
        dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
            <span style="color: #002200;">&#91;</span>self addOrUpdateEntryWithURL<span style="color: #002200;">:</span>fileURL metadata<span style="color: #002200;">:</span>metadata state<span style="color: #002200;">:</span>state version<span style="color: #002200;">:</span>version<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#91;</span>self performSegueWithIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;showDetail&quot;</span> sender<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>; 
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>We&#8217;re finally putting all of the helper methods we wrote to good use!  Here we:</p>
<ul>
<li>Use getDocURL to find the local Documents directory</li>
<li>Use getDocFilename to find an available filename in that directory</li>
<li>Alloc/init a PTKDocument</li>
<li>Call saveToURL to save it right away</li>
<li>Keep track of the (opened) and selected document</li>
<li>Add the entry to the table, and perform the showDetail segue</li>
</ul>
<p>Note that there is no guarantee that the completionHandler passed to saveToURL executes on the main thread, hence we have to use dispatch_async to run parts of the code on the main queue which need it.</p>
<p><em>Final Changes</em></p>
<p>OK, almost ready to test this out!  Just make these final changes to PTKMasterViewController.m:</p>

<div class="wp_codebox"><table><tr id="p12779119"><td class="code" id="p12779code119"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Add to end of viewDidLoad</span>
_objects <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Replace tableView:cellForRowAtIndexPath with the following</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>UITableViewCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView cellForRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
    UITableViewCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>tableView dequeueReusableCellWithIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cell&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    PTKEntry <span style="color: #002200;">*</span>entry <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_objects objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
    cell.imageView.image <span style="color: #002200;">=</span> entry.metadata.thumbnail;
    cell.textLabel.text <span style="color: #002200;">=</span> entry.description;
    cell.detailTextLabel.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>entry.version.modificationDate mediumString<span style="color: #002200;">&#93;</span>;    
&nbsp;
    <span style="color: #a61390;">return</span> cell;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Replace prepareForSegue with the following</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>prepareForSegue<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIStoryboardSegue <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>segue sender<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: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>segue identifier<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;showDetail&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// TODO</span>
    <span style="color: #002200;">&#125;</span> 
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Here we just initialize the objects array and configure our table view to display information about the documents.  We&#8217;ll fix up the segue and detail view controller later.</p>
<p>Compile and run your project, and you should now be able to tap the + button to create new documents:</p>
<p><a href="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/CreateDocs.png"><img src="http://d1xzuxjlafny7l.cloudfront.net/wp-content/uploads/2012/04/CreateDocs.png" alt="Creating local UIDocuments in PhotoKeeper" title="Creating local UIDocuments in PhotoKeeper" width="320" height="480" class="alignnone size-full wp-image-12790 bordered" /></a></p>
<p>If you look at the console output, you should see messages showing the full path the documents are being saved to, like this:</p>
<pre class="command">
File created at file://localhost/Users/rwenderlich/Library/Application%20Support/
iPhone%20Simulator/5.1/Applications/
194CFF63-BE3F-4CAF-90CC-BFA843C2169B/Documents/Photo%202.ptk
</pre>
<p>However this app has a big problem.  If you run the app again, nothing will show up in the list!  That&#8217;s because we haven&#8217;t added the code to list documents yet, so let&#8217;s do that now.</p>
<h2>Listing Local Documents</h2>
<p>To list local documents, we&#8217;re going to get the URLs for all the documents in the local Documents directory, and open up each one.  We&#8217;ll read the metadata out to get the thumbnail (but not the data, so things are efficient), then close it back up again and add it to the table view.</p>
<p>First let&#8217;s add the method that loads a document given a file URL.  Add this right above the &#8220;View lifecycle&#8221; section with awakeFromNib:</p>

<div class="wp_codebox"><table><tr id="p12779120"><td class="code" id="p12779code120"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#pragma mark File management methods</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>loadDocAtURL<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>fileURL <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Open doc so we can read metadata</span>
    PTKDocument <span style="color: #002200;">*</span> doc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PTKDocument alloc<span style="color: #002200;">&#93;</span> initWithFileURL<span style="color: #002200;">:</span>fileURL<span style="color: #002200;">&#93;</span>;        
    <span style="color: #002200;">&#91;</span>doc openWithCompletionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Check status</span>
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Failed to open %@&quot;</span>, fileURL<span style="color: #002200;">&#41;</span>;
            <span style="color: #a61390;">return</span>;
        <span style="color: #002200;">&#125;</span>
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Preload metadata on background thread</span>
        PTKMetadata <span style="color: #002200;">*</span> metadata <span style="color: #002200;">=</span> doc.metadata;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> fileURL <span style="color: #002200;">=</span> doc.fileURL;
        UIDocumentState state <span style="color: #002200;">=</span> doc.documentState;
        NSFileVersion <span style="color: #002200;">*</span> version <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSFileVersion currentVersionOfItemAtURL<span style="color: #002200;">:</span>fileURL<span style="color: #002200;">&#93;</span>;
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Loaded File URL: %@&quot;</span>, <span style="color: #002200;">&#91;</span>doc.fileURL lastPathComponent<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Close since we're done with it</span>
        <span style="color: #002200;">&#91;</span>doc closeWithCompletionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Check status</span>
            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Failed to close %@&quot;</span>, fileURL<span style="color: #002200;">&#41;</span>;
                <span style="color: #11740a; font-style: italic;">// Continue anyway...</span>
            <span style="color: #002200;">&#125;</span>
&nbsp;
            <span style="color: #11740a; font-style: italic;">// Add to the list of files on main thread</span>
            dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>                
                <span style="color: #002200;">&#91;</span>self addOrUpdateEntryWithURL<span style="color: #002200;">:</span>fileURL metadata<span style="color: #002200;">:</span>metadata state<span style="color: #002200;">:</span>state version<span style="color: #002200;">:</span>version<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;             
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Notice that we open the document, get what we need, and close it again rather than keeping it open permanently.  This is for two reasons:</p>
<ol>
<li>Avoid the overhead of keeping an entire UIDocument in memory when we just need one part</li>
<li>UIDocuments can only be opened and closed once (!)  UIDocument is a &#8220;one shot&#8221; class &#8211; you can just open it once and close it once.  If you want to open the same fileURL again, you have to create a new UIDocument instance.</li>
</ol>
<p>Right after this add these methods to perform the refresh:</p>

<div class="wp_codebox"><table><tr id="p12779121"><td class="code" id="p12779code121"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#pragma mark Refresh Methods</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>loadLocal <span style="color: #002200;">&#123;</span>
&nbsp;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span> localDocuments <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> defaultManager<span style="color: #002200;">&#93;</span> contentsOfDirectoryAtURL<span style="color: #002200;">:</span>self.localRoot includingPropertiesForKeys<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> options<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Found %d local files.&quot;</span>, localDocuments.count<span style="color: #002200;">&#41;</span>;    
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i<span style="color: #002200;">=</span><span style="color: #2400d9;">0</span>; i &lt; localDocuments.count; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span> fileURL <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>localDocuments objectAtIndex<span style="color: #002200;">:</span>i<span style="color: #002200;">&#93;</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>fileURL pathExtension<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span>PTK_EXTENSION<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Found local file: %@&quot;</span>, fileURL<span style="color: #002200;">&#41;</span>;
            <span style="color: #002200;">&#91;</span>self loadDocAtURL<span style="color: #002200;">:</span>fileURL<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>        
    <span style="color: #002200;">&#125;</span>
&nbsp;
    self.navigationItem.rightBarButtonItem.enabled <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>refresh <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>_objects removeAllObjects<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self.tableView reloadData<span style="color: #002200;">&#93;</span>;
&nbsp;
    self.navigationItem.rightBarButtonItem.enabled <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>self iCloudOn<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>self loadLocal<span style="color: #002200;">&#93;</span>;       
    <span style="color: #002200;">&#125;</span>        
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>This is pretty simple file management stuff &#8211; loadLocal calls loadDocAtURL for everything in the Documents directory, and refresh kicks this all off.</p>
<p>The reason we enable/disable the right bar button item is you shouldn&#8217;t be able to create a new file until we have retrieved the list of files.  This is because we need the list of files to guarantee a unique name when creating a new file.  This doesn&#8217;t much matter now since we get the list of files right away, but is good to have in place for when that isn&#8217;t the case with iCloud.</p>
<p>To try this out, add the following to the bottom of viewDidLoad:</p>

<div class="wp_codebox"><table><tr id="p12779122"><td class="code" id="p12779code122"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>self refresh<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Compile and run, and this time your app should correctly pick up the list of documents since last time it was run!</p>
<h2>Where To Go From Here?</h2>
<p>Here is a download with the state of the <a href="http://d1xzuxjlafny7l.cloudfront.net/downloads/PhotoKeeper1.zip">code sample</a> so far.</p>
<p>At this point you have the data model and UIDocument wrapper working and the ability to create and list files.  It might not look like much yet, but that&#8217;s the most critical part!</p>
<p>In the next part of the series, we&#8217;ll get this app fully functional and polished when it comes to local files.  We&#8217;ll customize our table view cells, add a detail view, support deleting and renaming, and more!  At that point you&#8217;ll be fully set to move to the iCloud :]</p>
<p>If you have any questions, comments, or suggestions about better ways to do things, please join the forum discussion below!  :]</p>
<p><img src="http://d1xzuxjlafny7l.cloudfront.net/downloads/RayWenderlich.jpg" class="photo alignleft" /><br />
<i>This is a blog post by site administrator <a href="http://www.raywenderlich.com/about">Ray Wenderlich</a>, an independent software developer and gamer.</i></p>
<p><a href="http://www.raywenderlich.com/12779/icloud-and-uidocument-beyond-the-basics-part-1">iCloud and UIDocument: Beyond the Basics. Part 1/4</a> is a post from: <a href="http://www.raywenderlich.com">Ray Wenderlich</a></p>
<div id="tweetbutton12779" class="tw_button" style="float:left;"><a href="http://twitter.com/share?url=http%3A%2F%2Fbit.ly%2FIEoozq&amp;via=rwenderlich&amp;text=iCloud%20and%20UIDocument%3A%20Beyond%20the%20Basics.%20Part%201%2F4&amp;related=rwenderlich&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fwww.raywenderlich.com%2F12779%2Ficloud-and-uidocument-beyond-the-basics-part-1" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://d1xzuxjlafny7l.cloudfront.net/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><img src="http://feeds.feedburner.com/~r/RayWenderlich/~4/rNSp-snqkeg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.raywenderlich.com/12779/icloud-and-uidocument-beyond-the-basics-part-1/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.raywenderlich.com/12779/icloud-and-uidocument-beyond-the-basics-part-1</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 6.049 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-05-16 09:50:18 -->

