<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[grokin.gs]]></title>
  <link href="http://levigroker.github.com/atom.xml" rel="self"/>
  <link href="http://levigroker.github.com/"/>
  <updated>2015-09-03T10:38:10-06:00</updated>
  <id>http://levigroker.github.com/</id>
  <author>
    <name><![CDATA[Levi Brown]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[360iDev 2015]]></title>
    <link href="http://levigroker.github.com/blog/360idev-2015/"/>
    <updated>2015-08-31T14:53:50-06:00</updated>
    <id>http://levigroker.github.com/blog/360idev-2015</id>
    <content type="html"><![CDATA[<p><a href="http://360idev.com">360iDev</a> was once again informative and inspirational.</p>

<p>This year, for me, was more inspirational than informative, which is not necessarily bad, but I think just a symptom of my session choices. I&rsquo;ve included a list below of the sessions I attended and would recommend, and then sessions I didn&rsquo;t attend but wanted to.</p>

<p>They are still working on transcoding all the <a href="http://vimeopro.com/360conferences/360idev-2015/">session videos</a> (which they put online for everyone for free!) so check back for updates.</p>

<h1>Recommended Sessions</h1>

<p>These are sessions I attended which are worth watching. I&rsquo;ve filtered out the sessions which didn&rsquo;t inspire or weren&rsquo;t technically interesting (to me).</p>

<ul>
<li><p><a href="http://360idev.com/sessions/something-deep-with-mike/">Something Deep With Mike</a><br/>
<a href="https://twitter.com/bmf">Mike Lee (@bmf)</a> talks about world modeling, how the models predict our current global situation, and what we can do as software engineers to aid in the shaping of our planet&rsquo;s future.</p>

<p>  This is a <strong>must watch</strong> presentation. My potentially inadequate description might make this talk sound like something you can skip, but that is entirely not correct. The concepts and information presented here are so important and relavent that this should be mandatory viewing for everyone.</p>

<p>  The 360iDev version of Mike&rsquo;s presentation is more refined and to the point than his UIKonf discussion, but YouTube has Mike&rsquo;s <a href="https://www.youtube.com/watch?v=SDZkKvC8r40">&ldquo;World Modelling&rdquo; UIKonf video</a> online at this time and is worth watching.</p></li>
<li><p><a href="http://360idev.com/sessions/decision-fatigue/">Decision Fatigue</a><br/>
<a href="https://twitter.com/Daniel1of1">Daniel Haight (@Daniel1of1)</a> gives us an interesting and informative look at how humans make decisions.</p>

<blockquote><p>Decision Fatigue is the name given to the effect in which the quality of your decision making deteriorates with the number of decisions you have to make.</p>

<p>What is interesting is that many studies have shown that the difficulty of the decisions actually have little effect on the rate of the deterioration, more so the quantity. This is to say that having to make a lot of ‘small’ or ‘easy’ decisions can seriously harm the quality of the ‘bigger’ decisions you make.</p>

<p>Have you ever had to repeatedly decide how you might implement an API design? How you’d implement a network layer? K&amp;R braces? tabs or spaces? withCompletionBlock: or just completionBlock:? Each of these decisions especially when made over and over can take away from the much more important decisions along the lines of “What is the ultimate goal of what we’re building?” or “Why are we implementing this?”</p></blockquote></li>
<li><p><a href="http://360idev.com/sessions/200-switching-your-brain-to-swift/">Switching Your Brain to Swift</a><br/>
<a href="https://twitter.com/gregheo">Greg Heo (@gregheo)</a> gives a compelling and well presented talk which primed me to get more into Swift.<br/>
<a href="http://vimeopro.com/360conferences/360idev-2015/video/137530879">[video]</a> <a href="http://gregheo.com/blog/switching-your-brain-to-swift/">[blog]</a></p>

<blockquote><p>We’re now a year into Swift. For those coming from Objective-C who are still testing the Swift waters, what do you need to do to switch your brain over to the new Swift way of thinking? What’s new, what’s the same, and what’s completely different when programming for the same platform in a new language?
Big-picture outline:
– focus on safety
– undefined behavior
– less dynamic behavior and fuzziness; more strong typing and predictability
– a little bit on Swift/Obj-C interop and how to make the transition</p></blockquote></li>
<li><p><a href="http://360idev.com/sessions/200-bringing-swift-into-your-objective-c-projects/">Bringing Swift into your Objective-C Projects</a><br/>
<a href="https://twitter.com/RCachATX">René Cacheaux (@RCachATX)</a> delivers some really awesome advice about best practices for moving over to Swift.</p>

<blockquote><p>Join us as we explore tips and tricks for introducing Swift source into Objective-C projects. We’ll cover where in the networking-model-UI stack to begin writing Swift, how to maximize the benefits of using Swift without re-writing your apps, and how to avoid some of the common pitfalls getting Swift and Objective-C working harmoniously together.</p></blockquote></li>
<li><p><a href="http://360idev.com/sessions/300-ios-testing-beyond-the-model/">iOS Testing: Beyond the Model</a><br/>
<a href="https://twitter.com/catehstn">Cate Huston (@catehstn)</a> gave an inspired session about how to better implement testing in a MVC structured GUI app.<br/>
<a href="https://vimeopro.com/360conferences/360idev-2015/video/138025340">[video]</a> <a href="http://www.catehuston.com/blog/2015/04/15/launching-ios-unit-testing-beyond-the-model/">[blog]</a></p>

<blockquote><p>Unit testing on iOS has always been a challenge, mainly because the ViewController creates a mix of UI and non-UI code. But, it’s totally possible to achieve good levels of coverage on view code for iOS, and this talk will cover some strategies for doing so, focusing on a real app (no contrived examples here!) Including: splitting up a ViewController to make a seam, verifying button actions, dealing with [self navigationController], handling asynchronous code, and how we can compare UIImages.</p></blockquote></li>
<li><p><a href="http://360idev.com/sessions/200-good-intentions-ii-enemy-of-the-state/">Good Intentions II: Enemy of the State</a><br/>
<a href="https://twitter.com/jaythrash">Jay Thrash (@jaythrash)</a> gives a very interesting proposal about using a state machine to organize app flow and to clean up View Controllers.<br/>
<a href="https://vimeopro.com/360conferences/360idev-2015/video/138034525">[video]</a></p>

<blockquote><p>In a world where ViewControllers shoulder the burden of managing ever-changing vagarities of application state logic and complex navigation stacks, one design pattern emerges from the past to lead us toward a better, brighter, and lighter future of app development.</p>

<p>In this sequel to last year’s blockbuster presentation, “Good Intentions: Building Better ViewControllers”, we will revive a venerable programming technique for explicitly defining application behaviors and thereby reducing the responsibilities of our much maligned ViewControllers.</p></blockquote></li>
</ul>


<h1>&ldquo;TODO&rdquo; Sessions</h1>

<p>I didn&rsquo;t attend these due to overlap in the schedule, but they sound like sessions which shouldn&rsquo;t be missed.</p>

<ul>
<li><p><a href="http://360idev.com/sessions/200-fancy-custom-transitions/">Fancy Custom Transitions</a><br/>
<a href="https://twitter.com/GravityBytes">Grant Davis (@gravitybytes)</a><br/>
<a href="http://vimeopro.com/360conferences/360idev-2015/video/137519217">[video]</a></p>

<blockquote><p>Develop powerful, beautiful custom transitions using the APIs introduced in iOS7. In this session we’ll explore how to make both simple animated custom transitions as well as more complicated, interactive transitions.</p></blockquote></li>
<li><p><a href="http://360idev.com/sessions/300-solving-auto-layout-problems/">Solving Auto Layout Problems</a><br/>
Jack Cox</p>

<blockquote><p>Auto layout is hard. It requires developers to think different about structuring and manipulating views. If the developer doesn’t express themselves 100% correctly the results can be messy. And auto layout doesn’t help with it’s obtuse error message and verbose messages. This talk will cover some uses of auto layout that bedevil developers like: using auto layout in scroll views, self sizing tables and collections, and debugging conflicts.</p></blockquote></li>
<li><p><a href="http://360idev.com/sessions/100-apple-pay-what-happens-when-you-tap/">Apple Pay: What happens when you tap?</a><br/>
<a href="https://twitter.com/stepanhruda">Stepan Hruda (@stepanhruda)</a><br/>
<a href="http://vimeopro.com/360conferences/360idev-2015/video/137558116">[video]</a></p>

<blockquote><p>Arguably Apple Pay might be the nudge that NFC needed to go mainstream. Let’s talk some implementation details of what happens when you tap your iPhone or Apple Watch and why tokenization is a $20 word for a 5-cent software concept.</p>

<p>We’ll cover the basics of credit cards, NFC and in-app Apple Pay payments.</p></blockquote></li>
<li><p><a href="http://360idev.com/sessions/mastering-auto-layout/">Mastering Auto Layout</a><br/>
<a href="https://twitter.com/justin">Justin Williams (@justin)</a><br/>
<a href="http://vimeopro.com/360conferences/360idev-2015/video/137550517">[video]</a></p>

<blockquote><p>The third-part of Justin’s 360iDev Auto Layout trilogy! Learn how to take full advantage of Apple’s modern layout toolkit in your iOS 9 and OS X El Capitan apps. Justin will walk you through crafting custom interface elements using Auto Layout, layout anchors, dynamically sized elements, keeping your sanity with size classes, and Swift 2.</p></blockquote></li>
<li><p><a href="http://360idev.com/sessions/200-building-habits-keeping-users-engaged/">Building Habits: keeping users engaged</a><br/>
<a href="https://twitter.com/mostgood">Sally Shepard (@mostgood)</a><br/>
<a href="http://www.slideshare.net/mostgood/building-habits-keeping-users-engaged">[slides]</a></p>

<blockquote><p>So you’ve got some downloads but downloads don’t necessarily equate to active users. How can you engage a first time user? How can you keep them coming back to your app?
The psychology of building habits</p>

<ul>
<li>Joyful first experiences</li>
<li>The awesome power of email</li>
<li>Deep-linking</li>
<li>Pushing for good</li>
<li>Helpful help sections</li>
</ul>
</blockquote></li>
</ul>


<h1>Game Jam</h1>

<p>As usual, this year I participated in the &ldquo;Game Jam&rdquo; on Tuesday night. Since the idea of the game jam has transitioned from building an actual game to more of a &ldquo;stay up late and code on something&rdquo; feel, I take the opportunity to build something I wouldn&rsquo;t normally get a chance to play with. This year I chose to attempt to build a &ldquo;cheat app&rdquo; for a word game called <a href="https://itunes.apple.com/us/app/capitals-free-word-battle/id968456900?mt=8">Capitals</a> (which is pretty fun).</p>

<p>The idea sounds simple enough&hellip; take a screen shot, run it through an Optical Character Recognition (OCR) process to identify the available letters, then pass those letters into an anagram algorithm to produce a list of possible words.</p>

<p>I might write up a more detailed post on my findings, but the short version is that I spent most of my time trying to get the OCR engine, <a href="https://github.com/tesseract-ocr/tesseract">Tesseract</a> to recognize the characters in the screen shot. With some help from fellow 360iDev attendees I eventually managed to get the engine to recognize 90 percent of the letters&hellip; not good enough. So the idea didn&rsquo;t merit a demo at the Gam Jam review, and is &ldquo;on the shelf&rdquo; for future attempts.</p>

<h1>Con-clusion</h1>

<p>The 360iDev conference has always been about the people and the community. This year was no exception. We, as iOS developers, have a great community with many very smart and open people in it. As with any community I care about, these are the tenets I try to follow:</p>

<ul>
<li>Be kind and supportive</li>
<li>Contribute</li>
<li>Be thoughtful</li>
<li>Take responsibility</li>
</ul>


<p>Cheers,</p>

<p>Levi</p>

<hr />

<p>Updated September 3, 2015 with additional video and blog links.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Size of Our Sun]]></title>
    <link href="http://levigroker.github.com/blog/the-size-of-our-sun/"/>
    <updated>2015-06-18T12:44:47-06:00</updated>
    <id>http://levigroker.github.com/blog/the-size-of-our-sun</id>
    <content type="html"><![CDATA[<p>While talking with my girls about the weather, we noticed the weather forecast on Sarah&rsquo;s phone and saw an icon of the moon and stars, and I had to explain a few things.</p>

<ol>
<li>It bothers me that &ldquo;night time&rdquo; is commonly represented by an icon of the moon. The moon is out durring the day just as much as it is out durring the night.</li>
<li>Often icons like this represent the moon as a crescent, and there&rsquo;s stars inside the concave part of the crescent. This is implying that the star is <strong>in front</strong> of the moon.</li>
</ol>


<p>Do an <a href="https://www.google.com/search?q=nighttime+weather+icon">image search for &ldquo;night time weather icon&rdquo;</a> and you&rsquo;ll see plenty which look like this:<br/>
<img src="http://levigroker.github.com/images/posts/2015-06-18-the-size-of-our-sun/night_icon.png" title="night icon" alt="night icon"></p>

<p>So I mentioned that we&rsquo;d be in big trouble if there was a star in front of the moon, and started to try to explain that many stars are much like our sun, and our sun is very big and very hot and if it was close enough to be between us and the moon like in the icon, we&rsquo;d be toast.</p>

<p>But then I balked in my explanation, because I wasn&rsquo;t sure what the relative size of the sun was to our lunar orbit. I didn&rsquo;t know if the sun <em>would actually fit</em> inside the orbit of the moon (regardless of the consequences). So I had to look it up, and then make this graphic to get an idea of the relative sizes:</p>

<p><a href="http://levigroker.github.com/images/posts/2015-06-18-the-size-of-our-sun/SizeOfOurSun.png"><img src="http://levigroker.github.com/images/posts/2015-06-18-the-size-of-our-sun/SizeOfOurSun_small.jpg" title="size of our sun" alt="size of our sun"></a><br/>
Click/Tap on the image for a different look at higher resolution (can you see the moon!?). Original image credit: <a href="http://www.nasa.gov/multimedia/imagegallery/image_feature_1197.html">NASA</a></p>

<p>Yeah, no way the sun is fitting between the Earth and Moon. In fact, the sun is about 3.6 times as big as the distance between the Earth and moon!</p>

<p>Our sun is so big, if the Earth was in the center of a ball the diameter of the Moon’s orbit, the Sun could almost hold two of these balls side by side!</p>

<p>The details:<br/>
Our sun is 1,391,684 km in diameter (1712 pixels). <a href="https://en.wikipedia.org/wiki/Sun">[Sun]</a><br/>
The Earth is 12,742 km in diameter (~16 pixels). <a href="https://en.wikipedia.org/wiki/Earth">[Earth]</a><br/>
The Moon is 3 474.8 km in diameter (~4 pixels). <a href="https://en.wikipedia.org/wiki/Moon">[Moon]</a><br/>
The average distance from the center of the Earth to the center of the moon is 384,400 km (~473 pixels). <a href="https://en.wikipedia.org/?title=Lunar_distance_(astronomy">[ref]</a>)<br/>
* Please note, all pixel size references are to the <a href="http://levigroker.github.com/images/posts/2015-06-18-the-size-of-our-sun/SizeOfOurSun.png">full scale image</a></p>

<p>1,391,684 km / (384,400 km x 2) = 1.81</p>

<p>The Sun is 1.81 times as big as the average diameter of the Moon&rsquo;s orbit around Earth!</p>

<p>WOW, the sun is <em>big</em>.</p>

<p>Now that we know what the relative size of the Sun is to the Lunar Orbit, take a look at <a href="http://www.businessinsider.com/earth-size-compared-to-sun-graphic-2015-1">this</a> for an idea of how big (or small!) our sun is in general.</p>

<hr />

<p>Revised June 19 2015, with updated graphic, edited content, and inclusion of sun comparison link (thanks Bob).</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GRKImageCrop]]></title>
    <link href="http://levigroker.github.com/blog/grkimagecrop/"/>
    <updated>2015-04-28T13:53:26-06:00</updated>
    <id>http://levigroker.github.com/blog/grkimagecrop</id>
    <content type="html"><![CDATA[<p>A UIImage category which provides &ldquo;visible&rdquo; pixel cropping capabilities.</p>

<p>A given image can be rectangularly cropped based on calculated insets to &ldquo;visible&rdquo; pixels.
Visible pixels are those whose alpha component are greater than or equal to a given alpha
threshold.</p>

<p>Available on github: <a href="https://github.com/levigroker/GRKImageCrop">https://github.com/levigroker/GRKImageCrop</a></p>

<p><img src="http://levigroker.github.com/images/posts/2015-04-28-grkimagecrop/Demo.gif" title="demo" alt="demo"></p>

<h3>Installing</h3>

<p>If you&rsquo;re using <a href="http://cocopods.org">CocoPods</a> it&rsquo;s as simple as adding this to your
<code>Podfile</code>:</p>

<pre><code>pod 'GRKImageCrop'
</code></pre>

<p>otherwise, simply add the contents of the <code>GRKImageCrop</code> subdirectory to your
project.</p>

<h3>Documentation</h3>

<p>To use, simply import <code>UIImage+GRKImageCrop.h</code>:</p>

<pre><code>#import "UIImage+GRKImageCrop.h"
</code></pre>

<p>Then you can use the category to create a cropped image from a given image:</p>

<pre><code>[image cropImageBelowAlphaThreshold:0.0f completion:^(UIImage *croppedImage, NSError *error) {
    if (croppedImage)
    {
        //Use croppedImage
    }
    else
    {
        //Hanlde error
    }
}];
</code></pre>

<p>The only expected error would be memory related.</p>

<p>Additional documentation is available in <code>UIImage+GRKImageCrop.h</code> and example usage
can be found in the <code>GRKImageCropTestApp</code>.</p>

<h4>Disclaimer and Licence</h4>

<ul>
<li>Inspiration was taken from:

<ul>
<li><a href="https://developer.apple.com/library/mac/qa/qa1509/_index.html">https://developer.apple.com/library/mac/qa/qa1509/_index.html</a></li>
<li><a href="http://stackoverflow.com/a/1262893/397210">http://stackoverflow.com/a/1262893/397210</a></li>
<li><a href="http://stackoverflow.com/a/12617031/397210">http://stackoverflow.com/a/12617031/397210</a></li>
<li><a href="https://github.com/wrep/UIImage-Trim">https://github.com/wrep/UIImage-Trim</a></li>
</ul>
</li>
<li>I have made use of image cropping code from <a href="http://stackoverflow.com/a/25293588/397210">http://stackoverflow.com/a/25293588/397210</a></li>
<li>This work is licensed under the <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>.
Please see the included LICENSE.txt for complete details.</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CreateTextFileHere]]></title>
    <link href="http://levigroker.github.com/blog/createtextfilehere/"/>
    <updated>2015-03-31T14:58:28-06:00</updated>
    <id>http://levigroker.github.com/blog/createtextfilehere</id>
    <content type="html"><![CDATA[<p><a href="https://github.com/levigroker/CreateTextFileHere">CreateTextFileHere</a> is a manually activated AppleScript applet used to create a text file at the current Finder location with <a href="http://www.bbedit.com/">BBEdit</a></p>

<p>This utility works in tandem with the &lsquo;bbedit&rsquo; command line binary (which should
already be installed and functional at <code>/usr/local/bin/bbedit</code>).</p>

<p>The intention is for this utility to be accessed from the currently active Finder window and acts on the current directory in the Finder. I suggest adding CreateTextFileHere.app to the a Finder window&rsquo;s shelf (command-drag it into a Finder window at the top where the other tool icons are located) so it is available from the Finder as needed. Alternatively, it could be activated from the <a href="https://iworkautomation.com/numbers/script-menu.html">Script Menu</a>.</p>

<p>Thanks to the kind folk over at Bare Bones Software for letting me use a modified version of their text document icon.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Tools]]></title>
    <link href="http://levigroker.github.com/blog/tools/"/>
    <updated>2015-03-19T12:13:48-06:00</updated>
    <id>http://levigroker.github.com/blog/tools</id>
    <content type="html"><![CDATA[<p>Everyone works in different ways and employ different tools to do the things they want to do. Here&rsquo;s my curated list of tools I find I keep coming back to.</p>

<h3>Development</h3>

<p><a href="http://www.git-tower.com">Tower</a><br/>
The best Mac GUI git client I&rsquo;ve tried.</p>

<p><a href="http://cocoapods.org">CocoaPods</a><br/>
Third party code dependency manager.</p>

<p><a href="https://kapeli.com/dash">Dash</a><br/>
Awesome documentation browser. Handles many languages and doc sets, but I use it primarily for Cocoa.</p>

<p><a href="http://simpholders.com">SimPholders 2</a><br/>
For finding and inspecting the contents of your app in the simulator.</p>

<p><a href="http://www.macroplant.com/iexplorer/">iExplorer</a><br/>
For inspecting the contents of your app (or others) on-device, this is a great tool.</p>

<p><a href="http://rentzsch.github.io/mogenerator/">mogenerator</a><br/>
If you&rsquo;re working with CoreData, you should be using this tool to abstract your object classes.</p>

<p><a href="https://fabric.io">Fabric</a><br/>
iOS crash reporting, usage statistics, beta build distribution, and more.</p>

<p><a href="https://code.google.com/p/cocoa-rest-client/">Cocoa Rest Client</a><br/>
A simple GUI alternative to <code>curl</code> for testing ReST endpoints.</p>

<p><a href="http://www.cocoajsoneditor.com">Cocoa JSON Editor</a><br/>
Super nice GUI tool for creating and editing JSON files.</p>

<p><a href="http://www.cockos.com/licecap/">licecap</a><br/>
Create animated gifs. Really nice for quick app demos on github.</p>

<p><a href="http://www.kevincallahan.org/software/accessorizer.html">Accessorizer</a><br/>
Great timesaver for generating boilerplate Objective C code, though Objective-C&rsquo;s language updates have made this tool less useful than it used to be.</p>

<h3>General</h3>

<p><a href="https://agilebits.com/onepassword">1Password</a><br/>
A secure vault for passwords, credit cards, passports, etc. Seriously the first thing I install on a new device.</p>

<p><a href="https://db.tt/ktbXT8tW">Dropbox</a> (referral link)<br/>
Secure online file storage and sharing. The second thing I install on a new machine, primarily to sync 1Password vaults and other app settings.</p>

<p><a href="http://www.barebones.com/products/bbedit/">BBEdit</a><br/>
<em>The</em> text editor. I&rsquo;ve been using this since&hellip; well since I can remember. It does it all and doesn&rsquo;t get in your way. Installed almost immediately on a new machine.</p>

<p><a href="http://www.obdev.at/products/littlesnitch/index.html">Little Snitch</a><br/>
Basically a firewall for outgoing network connections. Probably the fourth thing I install on a new machine.</p>

<p><a href="http://qsapp.com">Quicksilver</a><br/>
A keyboard activated launcher and action performer (hard to describe). It is kind of like spotlight, but with more customizability and functionality.</p>

<p><a href="http://getpocket.com">Pocket</a><br/>
Bookmarking and reading app. Desktop, iOS, and web. A great way to keep hold of the gems one finds while surfing, Twitter, etc.</p>

<p><a href="http://www.acqualia.com/soulver/">Soulver</a><br/>
Awesome calculator for problem solving.</p>

<p><a href="http://www.yummysoftware.com">Yummy FTP</a><br/>
The best FTP/SFTP Mac GUI client I have tried.</p>

<p><a href="https://agilebits.com/knox">Knox</a><br/>
Simplifies creation and management of encrypted disk images. Everything that doesn&rsquo;t go in 1Password goes in here.</p>

<p><a href="https://www.peterborgapps.com/lingon/">Lingon</a><br/>
A GUI for creating and managing <code>launchd</code> configurations.</p>

<p><a href="http://manytricks.com/namemangler/">Name Mangler</a><br/>
Rename batches of files via a nice GUI.</p>

<p><a href="http://tapbots.com">Tweetbot</a><br/>
Twitter client for Mac and iOS.</p>

<p><a href="https://slack.com">Slack</a><br/>
Team collaboration and communication tool.</p>

<p><a href="http://airmailapp.com">Airmail</a><br/>
The best, but not perfect, email client I have tried since giving up on Mail.app.</p>

<p><a href="https://secure.backblaze.com/r/00mdf8">Backblaze</a> (referral link)<br/>
Offsite painless backup solution.</p>

<p><a href="http://www.macbartender.com">Bartender</a><br/>
De-clutter your menu bar. This manages all the little menubar warts that seem to show up with various tools. Keeps things nicely tucked away, but accessable.</p>

<p><a href="http://www.bettertouchtool.net">BetterTouchTool</a><br/>
A tool for configuring your interaction with a mouse or trackpad. Basically it allows you to program various gestures, clicks, taps, etc. to do any number of things.</p>

<p><a href="https://github.com/jbtule/cdto">cd to</a><br/>
A great little app which you install in your Finder &ldquo;shelf&rdquo; to open a terminal window at the current Finder location. It&rsquo;s a huge timesaver if you are moving between the finder and Terminal a lot.<br/>
There&rsquo;s an updated <a href="http://cl.ly/3U01352I293L">Yosemite icon</a> (from <a href="https://github.com/jbtule/cdto/issues/9">https://github.com/jbtule/cdto/issues/9</a>) which you&rsquo;ll most likely want too.</p>

<p><a href="https://github.com/levigroker/CreateTextFileHere">CreateTextFileHere</a> (shameless self promotion)<br/>
Another little app which sits in your Finder &ldquo;shelf&rdquo; to create a text file at the current Finder location. Created by yours truly.</p>

<p><a href="http://www.degreesapp.com">Degrees</a><br/>
A little weather widget. I use the Mac menubar version. It&rsquo;s nice and unobtrusive.</p>

<p><a href="http://unarchiver.c3.cx/unarchiver">The Unarchiver</a><br/>
Far better tool than Mac OS X&rsquo;s standard unarchiving tool. It handles so many more file formats.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Frustrations With Xcode Bots]]></title>
    <link href="http://levigroker.github.com/blog/frustrations-with-xcode-bots/"/>
    <updated>2015-03-05T16:15:00-07:00</updated>
    <id>http://levigroker.github.com/blog/frustrations-with-xcode-bots</id>
    <content type="html"><![CDATA[<p>Truly I want to like Xcode Bots, and I want them to work for my needs, but I got frustrated enough to tweet this not long ago:</p>

<blockquote><p>3:45 PM MT - 3 Mar 2015 <a href="https://twitter.com/levigroker/status/572890492603510784">&ldquo;I’m so done being bitten and frustrated with Xcode Bots. What a steaming pile. &lt;/rant&gt;&rdquo; -levigroker</a></p></blockquote>

<p>This frustration was caused by the latest in a long line of frustrations and their workarounds. Specifically, our bots are now spontaneously failing because of this error:</p>

<blockquote><p>&ldquo;Failed to mmap. Could not write data: Invalid argument (-1)&rdquo;
<img src="http://levigroker.github.com/images/posts/2015-03-05-frustrations-with-xcode-bots/build_service_error.png" title="build service error" alt="build service error"></p></blockquote>

<p><em>(don&rsquo;t be fooled by the &ldquo;Fix It&rdquo; button which doesn&rsquo;t seem to)</em></p>

<p>I&rsquo;m not the only one, as there are others on the <a href="https://devforums.apple.com/thread/254233">Apple Dev Forums</a> (login required) which are experiencing the same (or very similar) issue. The suggested workaround is to downgrade from Xcode 6.1.1 to 6.1. Yeah, I&rsquo;m not about to do that, so our CI build is broken, and I&rsquo;m left with no choice but to go back to <a href="http://jenkins-ci.org">Jenkins</a>. Honestly, that kind of gives me a sense of relief since I know I can get Jenkins to perform all the tasks I need, and I know if our CI build breaks it will be <em>my</em> fault and not an external dependency like Xcode Bots, over which I have no control.</p>

<p>I mentioned a long line of frustrations with Xcode Bots, and that&rsquo;s true. I&rsquo;ve not taken the time to try to document them all, but here&rsquo;s some off the top of my head:</p>

<ul>
<li>In my post <a href="http://levigroker.github.com/blog/xcode-bot-keychain-configuration/">Xcode Bot Keychain Configuration</a> I mentioned the fact that the bot server does not seem to fetch non-development provisioning profiles, and the steps needed to work around this issue.</li>
<li>Because of the aforementioned provisioning profile issue, we have <em>never</em> been able to get our Mac app build to work. We always get a provisioning profile mismatch error. We even went so far as to copy the developer cert and private key into the bot&rsquo;s keychain&hellip;</li>
<li>Inexplicably, a CI build will fail, and automatically rebuild, which will then succeed.</li>
<li>If a build (&ldquo;integration&rdquo;) succeeds, we get two for the price of one (no idea why&hellip; no new commits triggered it).</li>
<li>The web UI is&hellip; gone? In previous builds of the Xcode Bot server there was a web UI which presented the details of each build. This was removed, so any truly useful information must be gathered from Xcode.</li>
<li>Tracking down build system issues is laborious and cumbersome. The only real source of valuable information is the raw &ldquo;Build Log&rdquo; file, which can be viewed from within Xcode, but only after the integration has finished (no &ldquo;tail -f&rdquo;-like behavior), but be prepared to wait and keep scrolling as this file loads, slowly, with no UI feedback from your remote build server.</li>
<li>In general, the internals of the Xcode Bot system are so black box and inaccessible that debugging the process, understanding how it works, or extending it, is a non-trivial time investment which I&rsquo;d rather use to be working on actual projects.</li>
</ul>


<p>After all this, I still have high hopes for Xcode Bots, I do want to like them, and I look forward to the day when I can use them for my needs. That day is not today, unfortunately.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Xcode Bot Keychain Configuration]]></title>
    <link href="http://levigroker.github.com/blog/xcode-bot-keychain-configuration/"/>
    <updated>2015-03-05T15:56:00-07:00</updated>
    <id>http://levigroker.github.com/blog/xcode-bot-keychain-configuration</id>
    <content type="html"><![CDATA[<p>The Xcode Bot server (as of 3.2.1) uses <code>/Library/Developer/XcodeServer/Keychains/Portal.keychain</code> to store the needed certs and keys used for codesigning (previously it used the <code>System.keychain</code>.</p>

<p>The server seems to only automatically download developement certs and profiles (not distribution) so we must manually populate the keychain with the dsitribution cert/key pairs needed and manually place the distribution profile(s) we need into the location which the server looks for them. In my <a href="https://github.com/levigroker/iOSContinuousIntegration">iOSContinuousIntegration</a> system I have a <code>pre_action.sh</code> script which handles copying the profiles from where they are committed in the repository to the proper location on the server for the bots to locate them, so no need to go into that here. The keychain is a bit more complicated&hellip;</p>

<p>(Shamelessly borrowed from <a href="http://stackoverflow.com/a/25934218/397210">http://stackoverflow.com/a/25934218/397210</a>)</p>

<ol>
<li><p>Copy the Portal keychain to your desktop:</p>

<pre><code> sudo cp /Library/Developer/XcodeServer/Keychains/Portal.keychain ~/Desktop/
 Password: your-administrator-password
 sudo chown `whoami`:staff ~/Desktop/Portal.keychain 
</code></pre></li>
<li><p>Set the Portal keychain password to &ldquo;123&rdquo;</p>

<pre><code> security set-keychain-password -o "`sudo cat /Library/Developer/XcodeServer/SharedSecrets/PortalKeychainSharedSecret`" ~/Desktop/Portal.keychain 
 New Password: 123
 Retype New Password: 123
</code></pre></li>
<li><p>Open the Keychain in Keychain Access:</p>

<pre><code> open -b com.apple.keychainaccess ~/Desktop/Portal.keychain
</code></pre></li>
<li><p>Unlock the &ldquo;Portal&rdquo; keychain using password &ldquo;123&rdquo; (This may not be needed as it may already be unlocked).</p></li>
<li><p>Add the needed keys to the &ldquo;Portal&rdquo; keychain. Generally you will want your AdHoc Distribution certificate and private key, assuming you&rsquo;re building for AdHoc distribution (for say, <a href="http://try.crashlytics.com/beta/">Crashlytics Beta</a>).</p></li>
<li><p>Make sure the private keys have the correct access rights (in the &ldquo;Access Control&rdquo; tab of the &ldquo;Get Info&rdquo; for the private keys in Keychain Access), &ldquo;xcsbuildd&rdquo;, &ldquo;xcscontrol&rdquo;, &ldquo;xcodebuild&rdquo; and &ldquo;codesign&rdquo; should be listed. &ldquo;xcsbuildd&rdquo;, &ldquo;xcscontrol&rdquo;, and &ldquo;xcodebuild&rdquo; are inside the Xcode binary&hellip; <code>/Applications/Xcode.app/Contents/Developer/usr/bin</code> while &ldquo;codesign&rdquo; is <code>usr/bin/codesign</code>. Finder&rsquo;s &ldquo;Go to Folder&hellip;&rdquo; command is useful for locating these binaries. Though you will likely need to &ldquo;unhide&rdquo; the <code>/usr</code> directory from the GUI.</p>

<p> This can be done by opening a terminal and issuing the command:</p>

<pre><code> sudo chflags nohidden /usr
</code></pre>

<p> Then navigate to <code>/usr/bin</code> and select the codesign executable from the file picker GUI in the &ldquo;Access Control List&rdquo; tab of the Keychain Access&rsquo;s Get Info dialog. Once added to the ACL you can (and should) re-hide <code>/usr</code> with this command:</p>

<pre><code> sudo chflags hidden /usr
</code></pre></li>
<li><p>Lock the &ldquo;Portal&rdquo; keychain, quit &ldquo;Keychain Access&rdquo;</p></li>
<li><p>Reset the Portal keychain password:</p>

<pre><code> security set-keychain-password -p "`sudo cat /Library/Developer/XcodeServer/SharedSecrets/PortalKeychainSharedSecret`" ~/Desktop/Portal.keychain 
 Password: your-administrator-password (optional step)  
 Old Password: 123
</code></pre>

<p> It may or may not ask you for your administrator password again, pay attention to the prompt.</p></li>
<li><p>Copy the Portal keychain back</p>

<pre><code>   sudo chown _xcsbuildd:_xcs ~/Desktop/Portal.keychain
   sudo cp ~/Desktop/Portal.keychain /Library/Developer/XcodeServer/Keychains/
</code></pre></li>
<li><p>Since the system caches open keychains, restart you computer.</p></li>
</ol>


<p>&hellip;all this because Xcode Bots don&rsquo;t copy non-development profiles.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Apple's In-App Purchase Receipts]]></title>
    <link href="http://levigroker.github.com/blog/apples-in-app-purchase-receipts/"/>
    <updated>2015-01-30T15:36:20-07:00</updated>
    <id>http://levigroker.github.com/blog/apples-in-app-purchase-receipts</id>
    <content type="html"><![CDATA[<p>Recently I&rsquo;ve been reading up on Apple&rsquo;s In-App Purchase system with the goal of understanding how to support various types of purchases. It seems to me that non-consumables are kind of the &ldquo;poster child&rdquo; in-app purchase, for the typical &ldquo;remove adds&rdquo; or &ldquo;unlock content&rdquo; models. Which makes sense, because, in-app purchases are pretty simple if you are talking about auto-renewing subscriptions, or non-consumable items. Simple because Apple sends you all the information you need in their receipt, and persists that information for you. The only thing you&rsquo;re required to do is allow the user to &ldquo;restore purchases&rdquo; which basically gives you the receipt information back as if a purchase was made. Easy.</p>

<p>Things get more complicated when you want to handle the <em>other</em> types of purchases. Specifically consumables and non-renewing subscriptions. Apple pretty much says: &ldquo;Here&rsquo;s the receipt for your purchase&hellip; you better keep track of it for your user. Oh, and we&rsquo;re never giving you this information again&hellip;&rdquo; or at least that&rsquo;s what it sounds like to me when reading through the &ldquo;Persisting Using the App Receipt” section of the <a href="https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/DeliverProduct.html">In-App Purchase Programming  Guide</a></p>

<p> Where it says:</p>

<blockquote><p>Information about consumable products and non-renewing subscriptions is added to the receipt when they’re paid for and remains in the receipt until you finish the transaction. After you finish the transaction, this information is removed the next time the receipt is updated—for example, the next time the user makes a purchase.</p></blockquote>

<p>So that means, you, as the developer, must have your own server to maintain a record of these kinds of purchases, and allow a mechanism for your user to restore these kinds of purchases (on a new device, for instance). That means building and maintaining your own server to handle this, or integrate with something like <a href="https://parse.com">Parse</a>. Not the end of the world, but&hellip;</p>

<p>That&rsquo;s kind of crummy.</p>

<p>Not only do you need to build/integrate with the server component, but now you must ask your users to create an account with your system so you can identify them to associate their purchases with their account. I&rsquo;m sure users are used to this, but it&rsquo;s still a drag.</p>

<p>So, I searched around and found  <a href="http://www.progressconcepts.com/blog/non-renewing-subscription-app-purchases-ios/">this post</a> which stated that non-renewing subscription information persisted in the receipt from Apple. Wait, what? This post is obviously crazy, the In-App Purchase Programming  Guide said that didn&rsquo;t happen&hellip;</p>

<p>But now, while reading through Apple&rsquo;s <a href="https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1">Receipt Validation Programming Guide</a> there&rsquo;s this statement in the &ldquo;In-App Purchase Receipt&rdquo; section:</p>

<blockquote><p>The in-app purchase receipt for a non-consumable product, auto-renewable subscription, non-renewing subscription, or free subscription remains in the receipt indefinitely.</p></blockquote>

<p>Note the <em>non-renewing subscription</em> is listed as remaining &ldquo;in the receipt indefinitely.&rdquo;</p>

<p>So maybe that post wasn&rsquo;t crazy, and we could use the receipt for non-renewing subscriptions(!) without the need for a server component. That&rsquo;s super interesting&hellip;</p>

<p>&hellip;but you&rsquo;re still out of luck if you want to deal in consumables.</p>

<p>P.S. I&rsquo;ve provided Apple with this feedback for their In-App Purchase Programming  Guide documentation; feel free to do so as well.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Managing Ssh Git Keys]]></title>
    <link href="http://levigroker.github.com/blog/managing-ssh-git-keys/"/>
    <updated>2015-01-30T11:26:32-07:00</updated>
    <id>http://levigroker.github.com/blog/managing-ssh-git-keys</id>
    <content type="html"><![CDATA[<p>Like many developers, I would guess, I have many <code>ssh</code> keys. Keys for various services such as <a href="https://github.com">github</a>, <a href="https://bitbucket.org">bitbucket</a>, and others, each with the potential for multiple accounts. Managing these keys when using git on the command line can be a pain, but I&rsquo;ve got a decent working solution.</p>

<h1>ssh-agent</h1>

<p><code>ssh-agent</code> is a process that sits around and helps <code>ssh</code> do its thing on your behalf. There are several helper apps which allow you to configure its behavior, but specifically we are interested in <code>ssh-add</code>.</p>

<p><code>ssh-add</code> is your friend, especially on Mac OS X.</p>

<p>It can be used to store credentials which, upon a connection attempt, <code>ssh</code> will use. <code>ssh</code> will try all the credentials in the list until it finds one which works.</p>

<p>You can get a listing of what keys are already &ldquo;known&rdquo; by the agent with <code>ssh-add -l</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>Moorea:~ levi<span class="nv">$ </span>ssh-add -l
</span><span class='line'><span class="m">2048</span> 7d:81:16:54:ae:cb:9b:da:b6:65:75:32:40:c6:1e:ac /Users/levi/.ssh/progroker_id_rsa <span class="o">(</span>RSA<span class="o">)</span>
</span><span class='line'><span class="m">1024</span> b5:86:9e:05:d3:ba:f1:57:71:90:d0:2e:a9:94:1a:47 /Users/levi/.ssh/id_dsa <span class="o">(</span>DSA<span class="o">)</span>
</span><span class='line'><span class="m">2048</span> d4:f4:8c:be:2d:cd:5d:06:55:4a:24:bd:c1:9c:83:2b /Users/levi/.ssh/id_rsa_bitbucket <span class="o">(</span>RSA<span class="o">)</span>
</span><span class='line'>Moorea:~ levi<span class="nv">$ </span>
</span></code></pre></td></tr></table></div></figure>


<p>And here&rsquo;s the awesome-sauce&hellip; you can add keys <strong>whose credentials get stored in the keychain</strong> with <code>ssh-add -K &lt;path_to_private_key&gt;</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>Moorea:~ levi<span class="nv">$ </span>ssh-add -K /Users/levi/.ssh/id_rsa_bitbucket
</span><span class='line'>Enter passphrase <span class="k">for</span> /Users/levi/.ssh/id_rsa_bitbucket:
</span><span class='line'>Passphrase updated in keychain: /Users/levi/.ssh/id_rsa_bitbucket
</span><span class='line'>Identity added: /Users/levi/.ssh/id_rsa_bitbucket <span class="o">(</span>/Users/levi/.ssh/id_rsa_bitbucket<span class="o">)</span>
</span><span class='line'>Moorea:~ levi<span class="nv">$ </span>
</span></code></pre></td></tr></table></div></figure>


<p>So, if your <code>ssh</code> key has a passphrase on it, that passphrase is now stored in your Mac OS X keychain, and when <code>ssh</code> is looking for credentials to make the connection with it can find the key <em>and</em> use it without you needing to enter your passphrase again.</p>

<p>Win.</p>

<h1>HTTPS</h1>

<p>Further, for bonus points, when you&rsquo;re not using <code>ssh</code>, but rather https, you can still use the keychain&hellip;</p>

<p>Being on Mac OS X, we have the <code>osxkeychain</code> which can be used to store and retrive the kind of information we need for authentication.</p>

<p>To set this up, add (or ensure it is already there) the <code>helper</code> line in the <code>[credential]</code> section of your <code>~/.gitconfig</code> file:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="o">[</span>credential<span class="o">]</span>
</span><span class='line'>        <span class="nv">helper</span> <span class="o">=</span> osxkeychain
</span><span class='line'>        <span class="nv">useHttpPath</span> <span class="o">=</span> <span class="nb">true</span>
</span></code></pre></td></tr></table></div></figure>


<p>This will allow git to query the OS keychain when it is looking for stored credentials.</p>

<p>If you have multiple accounts on the same system, you may want to tie a set of credentials to the full repository path, so you can access different repositories with different credentials. That&rsquo;s what the <code>useHttpPath = true</code> line does.</p>

<p>Now, once you authorize a connection to a specific repository those credentials will be stored in your keychain:</p>

<p><img src="http://levigroker.github.com/images/posts/2015-01-30-managing-ssh-git-keys/git_keychain.png" title="git keychain entries" alt="git keychain entries"></p>

<p>Win a second time.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Switching It Up]]></title>
    <link href="http://levigroker.github.com/blog/switching-it-up/"/>
    <updated>2014-10-31T16:46:52-06:00</updated>
    <id>http://levigroker.github.com/blog/switching-it-up</id>
    <content type="html"><![CDATA[<p>Having not posted anything here in quite some time I started to wonder &ldquo;why not?&rdquo; and discovered, after some introspection, that I have limited myself by considering this <em>just</em> a <em>technical</em> blog.</p>

<p>Often I would find myself with ideas for technical topics to write about, but faced with the daunting task of writing them up in a digestable format proved, obviously, too big a hurdle to overcome, and nothing actually got posted. So, I&rsquo;m switching it up a bit.</p>

<p>While I&rsquo;ll still happily write about technical topics which I come across, I also plan to delve into topics which are less technical, and perhaps even more of a personal or sociological nature.</p>

<p>With this change, I&rsquo;ve also updated the visual theme here to be a bit lighter and less <em>default</em>.</p>

<p>I certainly hope to write more here, and I certainly hope others will appreciate that effort.</p>

<p>Cheers, and <em>Happy Halloween!</em></p>

<p>Levi</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Lion &amp; Automounter]]></title>
    <link href="http://levigroker.github.com/blog/lion-and-automounter/"/>
    <updated>2013-03-11T11:05:00-06:00</updated>
    <id>http://levigroker.github.com/blog/lion-and-automounter</id>
    <content type="html"><![CDATA[<p>Mounting a remote filesystem via the network is something which Unix has been doing since,
well, the dawn of Unix. So, naturally, when trying to make use of large amounts of network
storage on a NAS from a Mac OS X based machine, one would assume that mounting the network
storage and having the mountpoint be maintained automatically should be a simple Unix
configuration. And there you&rsquo;d be partly correct&hellip;</p>

<p>Darwin does make use of the <code>automount</code> system to configure and maintain mountpoints, and
one can setup entries in the <code>/etc/fstab</code> to mount remote filesystems using various
protocols (NFS, SMB, AFP, etc.), and various posts about doing this have been around for
<a href="http://web.archive.org/web/20090831103644/http://blogs.sun.com/lowbit/entry/easy_afp_autmount_on_os">a long time</a>
. However, Mac OSX Lion <a href="https://discussions.apple.com/thread/3221944">seems to have broken this</a>
in such a way that the mount points are inaccessible (incorrect permissions) to all but
the <code>root</code> user.</p>

<p>Over the weekend I struggled with this for too long, and ultimately found a solution,
albeit a bit of a hack. Roll up your sleeves, get a new cup of tea, here we go&hellip;</p>

<h3>/etc/fstab</h3>

<p>As root, edit your <code>/etc/fstab</code> and add the mount point you want.
Note: <code>/etc/fstab</code> did not exist by default. No need to worry, just create it. The <em>magic</em>
syntax is:</p>

<pre><code>&lt;servername&gt;:/&lt;path&gt; &lt;mount_point&gt; url auto,url==afp://&lt;username&gt;:&lt;password&gt;@&lt;servername&gt;/&lt;path&gt; 0 0
</code></pre>

<p>Example:</p>

<pre><code>nas.grokers.net:/media /Network/media url auto,url==afp://levi:foopass@nas.grokers.net/media 0 0
</code></pre>

<p>That sets up a mount point at <code>/Network/media</code> which points to the AFP share <code>nas.grokers.net/media</code></p>

<p>If you do this, then tell <code>automount</code> to reload with <code>automount -cv</code> you&rsquo;ll be able to cd into
<code>/Network/media</code> and see the remote filesystem, but only as root (in Lion, at least).</p>

<p>As an aside, it pains me to embed a password in the filesystem like this. A long time ago,
I spent a lot of effort trying to figure out a way to dynamically load the password from
the Keychain instead of embedding it here. I researched how to use executable automount
configurations so I could fetch the password using <code>/usr/bin/security</code> but ultimately
could never get it to work, so I gave up. If you&rsquo;ve a way to do this, please <a href="mailto:levigroker@gmail.com">let me know</a>.</p>

<h3>root-only permissions work-around</h3>

<p>To avoid the root-only permissions on the mount point, it would appear a <a href="http://forums.plexapp.com/index.php/topic/14201-howto-automount-afpsmb-shares-using-autofs/?p=202429">solution</a>
is to unmount the mountpoint after <code>automount</code> loads the configuration in <code>/etc/fstab</code>.</p>

<p>I tried many different approaches to unmount the mountpoint using a <code>launchd</code> <code>/Library/LaunchAgent</code>
and even a user LaunchAgent, but through many attempts none of them seemed to take place
<em>after</em> <code>automount</code> had loaded the config, and thus the mountpoint was still root-only
accessible.</p>

<p>So, an AppleScript application as a Login Item seems to be the only way, but we don&rsquo;t have
to embed our password (yet again) in the applescript. Instead, I created a shell script to
do the deed:</p>

<pre><code>#!/bin/bash
diskutil unmount /Network/media &gt; /dev/null 2&gt;&amp;1
exit 0
</code></pre>

<p>(I saved it at <code>/Users/levi/Library/Automation/nas_mount_helper.sh</code> but it doesn&rsquo;t matter where you put it)</p>

<p>Then add a line to the <code>sudoers</code> file so the script will run as <code>root</code> without the need
for a password:</p>

<p><code>$ sudo visudo</code></p>

<pre><code>levi ALL = NOPASSWD: /Users/levi/Library/Automation/nas_mount_helper.sh
</code></pre>

<p>Now, to run this script as a Login Item, I created an AppleScript application using the
AppleScript editor app. The contents of the applescript is pretty basic:</p>

<pre><code>do shell script "sudo /Users/levi/Library/Automation/nas_mount_helper.sh"
</code></pre>

<p>Save the script as an application, and use the &ldquo;Users &amp; Groups&rdquo; System Preferences to add
it as a Login Item</p>

<p>Almost there&hellip;</p>

<p>Unfortunately, this didn&rsquo;t quite do it. Upon login the mount couldn&rsquo;t be navigated to via
the Finder because of some error about the original not being found, so&hellip;</p>

<p>Another shell script was needed to force the mount.</p>

<pre><code>#!/bin/bash
cd /Network/media
ls -la
exit 0
</code></pre>

<p>(I saved it at <code>/Users/levi/Library/Automation/nas_mount_helper2.sh</code> but it doesn&rsquo;t matter where you put it)</p>

<p>This one we want to run as ourself, so no <code>sudoers</code> entry is needed.</p>

<p>Add an additional line to the applescript to run this after we unmount the share:</p>

<pre><code>do shell script "sudo /Users/levi/Library/Automation/nas_mount_helper.sh"
do shell script "/Users/levi/Library/Automation/nas_mount_helper2.sh"
</code></pre>

<h3>Extra Credit</h3>

<p>Finally, to prevent the AppleScript application from being noticeable (showing up in the dock, etc.),
add the <code>LSUIElement</code> key to the <code>Info.plist</code> of the generated AppleScript application,
by contextually clicking on the app from the Finder, choosing &ldquo;Show Package Contents&rdquo;,
browse to <code>Contents/Info.plist</code>, and then edit the Info.plist to add the element:</p>

<pre><code>&lt;plist version="1.0"&gt;
  &lt;dict&gt;
    ...
    &lt;key&gt;LSUIElement&lt;/key&gt;
    &lt;string&gt;1&lt;/string&gt;
    ...
  &lt;/dict&gt;
&lt;/plist&gt;
</code></pre>

<p>Not all that elegant, unfortunately, but a workaround at least.</p>

<h3>Thanks</h3>

<p>Thanks to <a href="https://twitter.com/signed8bit">@signed8bit</a> for the moral support, and the wayback-machine.<br/>
Thanks to <a href="http://forums.plexapp.com/index.php/user/22159-soli/">Soli</a> for the unmount workaround idea.</p>

<h3>Comments</h3>

<p><a href="http://MaxProWeb.com">Max Yarchak</a></p>

<blockquote><p>I face the same issue. I&rsquo;ve build a script which does reconnect to wifi (network) and it solves the issue with permissions for me.<br/>
<a href="https://github.com/MaxProWeb/MacAutomountFix">https://github.com/MaxProWeb/MacAutomountFix</a></p></blockquote>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[HashBuilder]]></title>
    <link href="http://levigroker.github.com/blog/hashbuilder/"/>
    <updated>2013-02-12T17:48:00-07:00</updated>
    <id>http://levigroker.github.com/blog/hashbuilder</id>
    <content type="html"><![CDATA[<p>Creating custom data objects as subclasses of NSObject is something which tends to happen
quite often, and making those objects &ldquo;good citizens&rdquo; which can be reliably placed into
NS collections (<code>NSDictionary</code>, <code>NSSet</code>, <code>NSArray</code>, etc.) means taking a few extra steps.
One of these steps is to override <code>NSObject</code>&rsquo;s <code>- (BOOL)isEqual:(id)object</code> method, and,
of course if you do that, you should (read: <em>must</em>) also override <code>- (NSUInteger)hash</code>.</p>

<p>Providing a good hash value from your overridden <code>- (NSUInteger)hash</code> method is a deep
topic, luckily we can stand on the backs of giants, and use knowledge and techniques
which follow &ldquo;known good&rdquo; practices. With that in mind, I created a utility, HashBuilder,
which makes generating a suitable hash value trivial.</p>

<p><a href="https://github.com/levigroker/HashBuilder">HashBuilder</a> can be used to build a hash
result from contributed objects or hashes (presumably properties on your object which
should be considered in the isEqual: override). The intention is for the hash result to be
returned from an override to the <code>NSObject</code> <code>- (NSUInteger)hash</code> method.</p>

<h3>Documentation</h3>

<p>To use, create a HashBuilder object, contribute to it, then query the &lsquo;builtHash&rsquo;
property for the resulting hash.</p>

<pre><code>- (NSUInteger)hash
{
    HashBuilder *builder = [HashBuilder builder];

    [builder contributeObject:self.objectID];
    [builder contributeObject:self.occurredDate];
    [builder contributeObject:self.type];
    [builder contributeObject:self.objectURL];
    [builder contributeObject:self.tags];
    [builder contributeObject:self.count];

    NSUInteger retVal = builder.builtHash;

    return retVal;
}
</code></pre>

<p>It is prudent to consider the same properties when overriding your <code>- (BOOL)isEqual:(id)object</code>
method as well.</p>

<p>NOTE: The order of contribution <em>will</em> change the resulting hash, even if all
the same values are contributed. For example:</p>

<pre><code>HashBuilder *builder1 = [HashBuilder builder];
[builder1 contributeObject:@"a"];
[builder1 contributeObject:[NSNumber numberWithInteger:12345]];
NSUInteger hash1 = builder1.builtHash;

HashBuilder *builder2 = [HashBuilder builder];
[builder2 contributeObject:[NSNumber numberWithInteger:12345]];
[builder2 contributeObject:@"a"];
NSUInteger hash2 = builder2.builtHash;
</code></pre>

<p><code>hash1 != hash2</code></p>

<h3>Installing</h3>

<p>If you&rsquo;re using <a href="http://cocopods.org">CocoPods</a> it&rsquo;s as simple as adding this to your <code>Podfile</code>:</p>

<pre><code>pod 'HashBuilder', '~&gt; 1.0'
</code></pre>

<p>NOTE: HashBuilder makes use of techniques and concepts presented by <a href="http://www.mikeash.com/">Mike Ash</a> in his post entitled <a href="http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-hashing.html">Implementing Equality and Hashing</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Orientation Respectful UINavigationController]]></title>
    <link href="http://levigroker.github.com/blog/orientationrespectfulnavigationcontroller/"/>
    <updated>2012-11-16T13:39:00-07:00</updated>
    <id>http://levigroker.github.com/blog/orientationrespectfulnavigationcontroller</id>
    <content type="html"><![CDATA[<p>While working on a project for iOS 6 I ran into an interesting issue with rotations.</p>

<p>I wanted one of my views to rotate, but not others, and since <code>UIViewController</code>&rsquo;s <code>shouldAutorotateToInterfaceOrientation:</code> is deprecated in iOS 6 and the docs point at overriding <code>shouldAutorotate</code>, I swapped them out. But&hellip; <code>shouldAutorotate</code> didn&rsquo;t get called. Hrm? A little poking around and I see this in the <a href="http://developer.apple.com/library/ios/#releasenotes/General/RN-iOSSDK-6_0/_index.html">iOS 6 release notes</a>:</p>

<blockquote><p>Now, iOS containers (such as UINavigationController) do not consult their children to
determine whether they should autorotate. By default, an app and a view controller’s
supported interface orientations are set to UIInterfaceOrientationMaskAll for the iPad
idiom and UIInterfaceOrientationMaskAllButUpsideDown for the iPhone idiom.</p></blockquote>

<p>So, because my views are &ldquo;underneath&rdquo; a <code>UINavigationController</code> their <code>shouldAutorotate</code> methods are not getting called, only the parent <code>UINavigationController</code> is queried. That seems like an odd behavior to me, but it&rsquo;s easy enough to remedy. A subclass of <code>UINavigationController</code> which respects the desired behavior of the top view controller is all that&rsquo;s needed.</p>

<p>This UINavigationController subclass will query it&rsquo;s topmost view controller for desired rotation behavior, unlike the default implementation:</p>

<div><script src='https://gist.github.com/4090689.js'></script>
<noscript><pre><code>//
//  OrientationRespectfulNavigationController.h
//
//  Created by Levi Brown on 11/15/12.
//  Created by Levi Brown on 11/15/12. @levigroker
//  This work is licensed under a Creative Commons Attribution 3.0 Unported License
//  http://creativecommons.org/licenses/by/3.0/
//  Attribution to Levi Brown (@levigroker) is appreciated but not required.
//

/*
 This NavigationController will query it&#39;s topmost view controller for desired rotation behavior,
 unlike the default implementation.

 From the iOS 6 release notes:
 http://developer.apple.com/library/ios/#releasenotes/General/RN-iOSSDK-6_0/_index.html

 Now, iOS containers (such as UINavigationController) do not consult their children to
 determine whether they should autorotate. By default, an app and a view controller’s
 supported interface orientations are set to UIInterfaceOrientationMaskAll for the iPad
 idiom and UIInterfaceOrientationMaskAllButUpsideDown for the iPhone idiom.
 */

#import &lt;UIKit/UIKit.h&gt;

@interface OrientationRespectfulNavigationController : UINavigationController

@end
</code></pre></noscript></div>


<p>To use, simply include the source in your project, and select <code>OrientationRespectfulNavigationController</code> as the class to use in place of each <code>UINavigationController</code> you want to have this behavior:</p>

<p><img src="http://levigroker.github.com/images/posts/2012-11-16-orientationrespectfulnavigationcontroller/IBClassConfig.png" title="XCode configuration for UINavigationController class override" alt="XCode configuration for UINavigationController class override"></p>

<p>NOTE: I&rsquo;m by no means the first to figure this out. StackOverflow <a href="http://stackoverflow.com/questions/12520030/how-to-force-a-uiviewcontroller-to-portait-orientation-in-ios-6">has</a> <a href="http://stackoverflow.com/q/12777474/397210">several</a>  <a href="http://stackoverflow.com/a/12996924/397210">posts</a> which illustrate the problem and solution.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Powerful, CocoaPods Are!]]></title>
    <link href="http://levigroker.github.com/blog/powerful/"/>
    <updated>2012-11-08T10:38:00-07:00</updated>
    <id>http://levigroker.github.com/blog/powerful</id>
    <content type="html"><![CDATA[<p><a href="http://cocoapods.org">CocoaPods</a>, &ldquo;The Objective-C Library Manager,&rdquo; is something I&rsquo;ve been using now for a while and really enjoying it for integrating third party frameworks and components into my projects. If you&rsquo;re not familiar with it already, I <em>highly</em> recommend you look into it as it is really powerful and useful.</p>

<h3>Installing pods for multiple targets</h3>

<p>My projects generally have at least two targets; the main target and a test target. When I initially setup CocoPods for my projects with a</p>

<pre><code>$ pod install
</code></pre>

<p>it does not configure the test target to use the <code>Pods.xcconfig</code> which specify all the integration points for the included pods. And, finding where to manually configure the use of the <code>xcconfig</code> file for the test target took me a bit of digging.</p>

<p>You&rsquo;ll need to go into the project settings, on the info tab of the project (not the target) and expand each configuration in the &ldquo;Configurations&rdquo; area (just under &ldquo;Deployment Target&rdquo;). Then set each configuration to use the Pods configuration on any alternate targets (like my test target):</p>

<p><img src="http://levigroker.github.com/images/posts/2012-11-08-powerful/PodsxcconfigConfig.png" title="XCode configuration of xcconfig usage on targets" alt="XCode configuration of xcconfig usage on targets"></p>

<p>From then on the alternate targets will inherit from the <code>Pods.xcconfig</code> configuration as they should.</p>

<p>Similarly, some of the growing pains I&rsquo;ve had with my use of CocoaPods have been related to making sure the configurations inherit from the <code>Pods.xcconfig</code> configuration, specifically custom header and library search paths. So if you get build errors related to not being able to find headers or libraries double check the target&rsquo;s header and library search path build settings and ensure the first element is <code>$(inhertied)</code>. In general, I&rsquo;ve found the <a href="https://github.com/CocoaPods/CocoaPods/wiki">CocoPods Wiki</a> is a good place to start reading up, should you encounter issues.</p>

<h3>Using a Fork as a Pod</h3>

<p>Using &ldquo;off the shelf&rdquo; pods is as easy as the docs say&hellip; you simply search for the pod you want at <a href="http://cocoapods.org">http://cocoapods.org</a>, add a dependency in the <code>Podfile</code> and then run <code>pod update</code>. I&rsquo;ve found, however, that sometimes I want to fork a project that I&rsquo;m using as a pod so I can make changes. But how then to use the fork as a pod? It&rsquo;s not hard, actually.</p>

<p>I ran into <a href="http://stackoverflow.com/a/12393865/397210">this answer</a> which pointed me to the <a href="https://github.com/CocoaPods/CocoaPods/wiki/Dependency-declaration-options">CocoPods dependency declaration wiki entry</a>. Basically, all that needs to be done is to explicitly specify the git repository to use for the pod, instead of letting it use the default repository.</p>

<p>I&rsquo;ve had great luck with this approach for my extraction of the <a href="http://restkit.org">RestKit</a> ObjectMapping functionality (see my <a href="https://github.com/levigroker/RestKitObjectMapping">RestKitObjectMapping</a> fork). All I need to do now, to include this pod in my project is to add this line to my <code>Podspec</code> file:</p>

<pre><code>pod 'RestKitObjectMapping', :git =&gt; 'https://github.com/levigroker/RestKitObjectMapping.git'
</code></pre>

<p>Indeed, very powerful.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Shadow Knows]]></title>
    <link href="http://levigroker.github.com/blog/the-shadow-knows/"/>
    <updated>2012-10-25T16:46:00-06:00</updated>
    <id>http://levigroker.github.com/blog/the-shadow-knows</id>
    <content type="html"><![CDATA[<p>Adding drop shadows is a nice little UI touch which brings depth, and I like them, assuming they&rsquo;re done with subtlety.</p>

<p>That said, I&rsquo;ve been playing around with them a bit and have a couple of things to share.</p>

<ul>
<li>If your shadow is to be placed on a rectangular layer, use <code>layer.shadowPath</code> to increase performance.</li>
</ul>


<p>TIP: To easily create the rectangular path: <code>layer.shadowPath = [UIBezierPath bezierPathWithRect:layer.bounds].CGPath;</code></p>

<p>See <a href="https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/CALayer_class/Introduction/Introduction.html#//apple_ref/occ/instp/CALayer/shadowPath">Apple&rsquo;s CALayer documentation</a> where they say:</p>

<blockquote><p>If the value in this property is non-nil, the shadow is created using the specified path instead of the layer’s composited alpha channel. The path defines the outline of the shadow. It is filled using the non-zero winding rule and the current shadow color, opacity, and blur radius.</p>

<p>Specifying an explicit path usually improves rendering performance.</p></blockquote>

<ul>
<li><p>Similarly, using <code>layer.shouldRasterize = YES;</code> should increase performance (See the <a href="http://www.omnigroup.com/blog/entry/ipad_drop_shadow_performance_test/">iPad drop shadow performance</a> post from <a href="http://www.omnigroup.com/">The Omni Group</a>.</p></li>
<li><p>However, be <em>sure</em> to set the <code>layer.rasterizationScale</code> appropriately or you are likely to see pixelated content. This can easily be achieved by: <code>layer.rasterizationScale = [[UIScreen mainScreen] scale];</code></p></li>
</ul>


<p>So, to recap&hellip; drop shadows can add some really nice, subtle, depth and need not be an overt performance hit.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">CALayer</span> <span class="o">*</span><span class="n">layer</span><span class="p">;</span> <span class="c1">//Assumed to be initialized somewhere else</span>
</span><span class='line'><span class="n">layer</span><span class="p">.</span><span class="n">shadowPath</span> <span class="o">=</span> <span class="p">[</span><span class="n">UIBezierPath</span> <span class="nl">bezierPathWithRect:</span><span class="n">layer</span><span class="p">.</span><span class="n">bounds</span><span class="p">].</span><span class="n">CGPath</span><span class="p">;</span>
</span><span class='line'><span class="n">layer</span><span class="p">.</span><span class="n">shouldRasterize</span> <span class="o">=</span> <span class="n">YES</span><span class="p">;</span>
</span><span class='line'><span class="n">layer</span><span class="p">.</span><span class="n">rasterizationScale</span> <span class="o">=</span> <span class="p">[[</span><span class="n">UIScreen</span> <span class="n">mainScreen</span><span class="p">]</span> <span class="n">scale</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Elegant JSON Pretty Print for BBEdit]]></title>
    <link href="http://levigroker.github.com/blog/elegant-json-pretty-print-for-bbedit/"/>
    <updated>2012-09-07T10:52:00-06:00</updated>
    <id>http://levigroker.github.com/blog/elegant-json-pretty-print-for-bbedit</id>
    <content type="html"><![CDATA[<p>Working with JSON in BBEdit is great, but reading JSON is greatly enhanced by having it formatted nicely, and BBEdit doesn&rsquo;t have anything (that I&rsquo;ve found) which supports pretty printing JSON by default.</p>

<p>A while ago I found this post <a href="http://crisp.tumblr.com/post/2574967567/json-pretty-print-formatting-in-bbedit">http://crisp.tumblr.com/post/2574967567/json-pretty-print-formatting-in-bbedit</a> which worked great, but I ran into <a href="http://coderwall.com/p/g1cm2g">this elegant little snippet</a>. Inspired, I created a much simpler Text Filter for BBEdit:</p>

<div><script src='https://gist.github.com/3667653.js'></script>
<noscript><pre><code>#!/bin/bash
python -m json.tool
</code></pre></noscript></div>


<p>(drop this file in your <code>~/Library/Application Support/BBEdit/Text Filters</code> directory and then you can select it from BBEdit&rsquo;s Text->Apply Text Filter menu.</p>

<h2>Update</h2>

<h6>(Monday, September 24 2012)</h6>

<p>A little less elegant in the script, but this updated version has a nicer output:</p>

<div><script src='https://gist.github.com/3777091.js'></script>
<noscript><pre><code>#!/bin/bash
python -c &quot;import sys, json; print json.dumps(json.load(sys.stdin), indent=2)&quot;</code></pre></noscript></div>


<p>(Thanks to Bob Foster for this version)</p>

<h2>Update</h2>

<h6>(Monday, November 3 2014)</h6>

<p>Bob Foster passes attribution to <a href="http://ruslanspivak.com/2010/10/12/pretty-print-json-from-the-command-line/">http://ruslanspivak.com/2010/10/12/pretty-print-json-from-the-command-line/</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Give Me Back My ~/Library (!)]]></title>
    <link href="http://levigroker.github.com/blog/give-me-back-my-~-slash-library/"/>
    <updated>2012-09-07T10:39:00-06:00</updated>
    <id>http://levigroker.github.com/blog/give-me-back-my-~-slash-library</id>
    <content type="html"><![CDATA[<p>As a developer I need access to my Library directory, but Apple keeps hiding it from me with every OS update. Finally tired of manually typing <code>chflags nohidden ~/Library/</code> every time it disappeared, I created a simple LaunchAgent to do this for me every time I log into my machine.</p>

<p>Check it out:</p>

<div><script src='https://gist.github.com/3667585.js'></script>
<noscript><pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
&lt;plist version=&quot;1.0&quot;&gt;
&lt;dict&gt;
    &lt;key&gt;Label&lt;/key&gt;
    &lt;string&gt;com.levigroker.unhide_library&lt;/string&gt;
    &lt;key&gt;LingonWhat&lt;/key&gt;
    &lt;string&gt;/Users/levi/Library/Automation/unhide_library.sh&lt;/string&gt;
    &lt;key&gt;ProgramArguments&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;/Users/levi/Library/Automation/unhide_library.sh&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;RunAtLoad&lt;/key&gt;
    &lt;true/&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</code></pre></noscript></div>


<p>As an aside, I&rsquo;ll take this space to plug <a href="http://www.peterborgapps.com/lingon/">Lingon</a> (I have no affiliation), which is a nice GUI tool for managing LaunchAgents and saves you from editing XML and dropping to the command line to talk to <code>launchd</code>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Override Deprecated API Warning]]></title>
    <link href="http://levigroker.github.com/blog/override-deprecated-api-warning/"/>
    <updated>2012-05-07T15:58:00-06:00</updated>
    <id>http://levigroker.github.com/blog/override-deprecated-api-warning</id>
    <content type="html"><![CDATA[<p>Sometimes I need to make a call to a deprecated API (for DEBUG builds only, of course) and don&rsquo;t want to see the warning. This little preprocessor tip will hide that warning:</p>

<div><script src='https://gist.github.com/2630702.js'></script>
<noscript><pre><code>#ifdef DEBUG
#pragma clang diagnostic push
#pragma clang diagnostic ignored &quot;-Wdeprecated-declarations&quot;
    [TestFlight setDeviceIdentifier:[[UIDevice currentDevice] uniqueIdentifier]];
#pragma clang diagnostic pop
#endif
</code></pre></noscript></div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CoreData Browsing]]></title>
    <link href="http://levigroker.github.com/blog/coredata-browsing/"/>
    <updated>2012-03-15T17:01:00-06:00</updated>
    <id>http://levigroker.github.com/blog/coredata-browsing</id>
    <content type="html"><![CDATA[<p>Found a handy tool for browsing core data on the simulator. It&rsquo;s not very polished, but it allows you to perform fetch requests with predicates and get back results, which helps immensely when trying to understand what&rsquo;s happening inside your app&rsquo;s data at runtime.
Check it out:</p>

<p><a href="http://atastypixel.com/blog/browsing-core-data-databases-using-f-script">http://atastypixel.com/blog/browsing-core-data-databases-using-f-script/</a></p>

<p>I also found this answer on SO which helped me get bootstrapped by giving the location of the two needed files in the simulator:</p>

<p><a href="http://stackoverflow.com/a/5998072/397210">http://stackoverflow.com/a/5998072/397210</a></p>

<p>Happy CoreData spelunking!</p>

<p>P.S. <a href="https://twitter.com/tomhoag">@tomhoag</a> suggested this <a href="https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager">https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/</a> as well&hellip; looks handy!</p>

<h2>Update</h2>

<h6>(Monday, September 24 2012)</h6>

<p>Since the original post, I&rsquo;ve discovered <a href="http://itunes.apple.com/us/app/core-data-editor/id403025957?mt=12">Core Data Editor</a> which is really great and I recommend it. However, the fscript approach allows one to perform predicate based fetch requests which is not something the Core Data Editor supports (at this time?) and is invaluable, so having both tools around is still handy.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using NSURLProtocol for Injecting Test Data]]></title>
    <link href="http://levigroker.github.com/blog/using-nsurlprotocol-for-injecting-test-data/"/>
    <updated>2012-01-24T15:54:00-07:00</updated>
    <id>http://levigroker.github.com/blog/using-nsurlprotocol-for-injecting-test-data</id>
    <content type="html"><![CDATA[<p>I found <a href="http://www.infinite-loop.dk/blog/2011/09/using-nsurlprotocol-for-injecting-test-data/">this</a> extremely useful for mocking up calls to network services.</p>
]]></content>
  </entry>
  
</feed>
