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

<channel>
	<title>Codehackers</title>
	<atom:link href="http://codehackers.net/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://codehackers.net/blog</link>
	<description></description>
	<lastBuildDate>Thu, 20 May 2010 01:57:54 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Stone Hill Invoicer 2</title>
		<link>http://codehackers.net/blog/?p=102</link>
		<comments>http://codehackers.net/blog/?p=102#comments</comments>
		<pubDate>Wed, 12 May 2010 18:24:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://codehackers.net/blog/?p=102</guid>
		<description><![CDATA[	E.B. White once said &#8220;The best writing is rewriting.&#8221;  He wasn&#8217;t talking about Stone Hill Invoicer, but he could have been.
	I&#8217;m pleased to announce the release of Stone Hill Invoicer 2.  The entire application has been been rewritten, right down to it&#8217;s core.  Of course, that&#8217;s not all.  If you&#8217;ve used [...]]]></description>
			<content:encoded><![CDATA[<p>	E.B. White once said &#8220;The best writing is rewriting.&#8221;  He wasn&#8217;t talking about Stone Hill Invoicer, but he could have been.</p>
<p>	I&#8217;m pleased to announce the release of Stone Hill Invoicer 2.  The entire application has been been rewritten, right down to it&#8217;s core.  Of course, that&#8217;s not all.  If you&#8217;ve used previous versions of Invoicer, you&#8217;ll see lots of new stuff: quotes, uninvoiced items, a decent address book, folders, more powerful smart folders, Stone Hill Time Card integration, better searching, multiple companies, and an even cleaner and simpler design.</p>
<p>	If you&#8217;ve never used it before, here are a few key facts:</p>
<ol>
<li> If Stone Hill Invoicer had a MySpace page, it would say &#8220;Influences: iTunes, Mail, Brent Simmons and his Weblog, WWPD.&#8221;
<li> Stone Hill Invoicer uses 12 pieces of open source code, including <a href="http://codehackers.net/blog/?p=70">one that was written just for it</a>.
<li> Stone Hill Invoicer <a href="http://codehackers.net/blog/?p=96">got popovers</a> a couple weeks before the iPad was introduced, but it doesn&#8217;t expect you to believe that.
<li> The best way to get to know Stone Hill Invoicer better is to <a href="http://www.codehackers.net/stonehill2/Stone%20Hill%20Invoicer%202.zip">download it</a> and give it a try.
	</ol>
<p>	If you&#8217;ve got any questions or comments, <a href="mailto:warwick@codehackers.net">I&#8217;d be pleased to answer them</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://codehackers.net/blog/?feed=rss2&amp;p=102</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>In Defense of Online Help Pages</title>
		<link>http://codehackers.net/blog/?p=100</link>
		<comments>http://codehackers.net/blog/?p=100#comments</comments>
		<pubDate>Tue, 11 May 2010 07:58:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://codehackers.net/blog/?p=100</guid>
		<description><![CDATA[In a couple days I&#8217;m going to be releasing version 2 of Stone Hill Invoicer.  The last beta reports are trickling in, and like the superb testers they are, my beta group is working hard to find anything they can to comment on.  Among other things, todays email contained a bit of discussion [...]]]></description>
			<content:encoded><![CDATA[<p>In a couple days I&#8217;m going to be releasing version 2 of Stone Hill Invoicer.  The last beta reports are trickling in, and like the superb testers they are, my beta group is working hard to find anything they can to comment on.  Among other things, todays email contained a bit of discussion on the delay in the scrolling about box, a note about behaviour of the sourcelist when a certain sequence of clicks and keyboard arrows was applied, and two notes about the online help system.</p>
<p>I&#8217;ve done something a little different this time around.  In previous versions of Stone Hill I shipped a standard Apple Help Book.  This is an HTML help book with a few special tweaks that you can bundle up with your app so that it&#8217;s available through the Apple Help Viewer.  In this version, the &#8220;Stone Hill 2.0 Help&#8221; menu item opens your default web browser and directs you to a blog that I set up specially for the app.</p>
<p>There&#8217;s only one disadvantage compared to a help book for my app: it&#8217;s not local.</p>
<p>So what about the guy on a fourteen hour flight to Paris?  Will he be unable to work because he doesn&#8217;t have a local copy?  For Google Docs, I buy that argument.  For an invoicing app&#8217;s help system?  Not so much.  I&#8217;d like to imagine I write good enough apps that you don&#8217;t need the help system, but even if you do, a lack of access to it for a few hours is unlikely to kill your ability to be productive.</p>
<p>But what advantages does an online help system bring?  Even if the man on the airplane is mythical, there have to be a few advantages to make it a good idea.</p>
<p><b>1. It&#8217;s a lot easier on me</b></p>
<p>There are no good tools to generate help books.  They&#8217;re a pain to update and a pain to work with.  Writing entries in MarsEdit is a thousand times better than building a static site with mildly specialized HTML.</p>
<p><b>2. I <i>really</i> like the idea of being able to leave comments on documentation</b></p>
<p>I get the occasional email that mentions some tip or way of doing something that a customer came up with, asking if I want to put it in the help documentation.  Assuming it&#8217;s a great tip, and I have the time to dust off the help docs and repackage them and reupload the app, that&#8217;s still a huge turnaround time for something that&#8217;s as simple as a comment on a blog post.</p>
<p>With the online help system, I&#8217;ve left comments enabled.  Sure, I&#8217;ll have to put in a minute or two a day to deal with spam, but a few good tips and tricks from users will more than make up for that.</p>
<p><b>3. Updating the help without updating the app</b></p>
<p>I can&#8217;t justify making the user download a new copy of the app just to get a new revision of the help book.  Especially if I want to make lots of little revisions as I see the support mail come in.  In previous versions I&#8217;ve had to separate help and the FAQ, when really they&#8217;re the same thing, I just feel able to update one and not the other.</p>
<p><b>4. The Leopard and Snow Leopard help viewer isn&#8217;t very good</b></p>
<p>I&#8217;m sure there&#8217;s a very good reason for it somewhere, but a help viewer that insists on sitting on top of all other windows means that I can&#8217;t keep it open and use the app I need help with.  On my Powerbook this was a huge issue.  On my development machine (20&#8243; + 23&#8243; screens) it&#8217;s less of a problem, but still annoys me.</p>
<p>Your browser is an excellent document viewer.  We should use it for that.</p>
<p><b>5. Now I can link users directly to a piece of documentation</b></p>
<p>In the past, I&#8217;ve actually copied and pasted entire help book entries, because the help entry describes exactly what&#8217;s being asked, they just didn&#8217;t check for it.  With the help entries online, I can now include a link in the email, saving me from having to reformat any pictures and text in the file.</p>
]]></content:encoded>
			<wfw:commentRss>http://codehackers.net/blog/?feed=rss2&amp;p=100</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quirky Things in the Stone Hill Invoicer 2 Interface</title>
		<link>http://codehackers.net/blog/?p=96</link>
		<comments>http://codehackers.net/blog/?p=96#comments</comments>
		<pubDate>Mon, 10 May 2010 00:51:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://codehackers.net/blog/?p=96</guid>
		<description><![CDATA[When it came time to update Stone Hill Invoicer&#8217;s design to be a little more modern, I couldn&#8217;t resist playing around a bit. ﻿  Some of this experimentation didn&#8217;t make it into the final app, but I think it&#8217;s fun to show it off anyhow.
Popovers
When the iPad announcement came out, I&#8217;ll admit I was thrilled about [...]]]></description>
			<content:encoded><![CDATA[<p>When it came time to update Stone Hill Invoicer&#8217;s design to be a little more modern, I couldn&#8217;t resist playing around a bit. ﻿  Some of this experimentation didn&#8217;t make it into the final app, but I think it&#8217;s fun to show it off anyhow.</p>
<p><strong>Popovers</strong></p>
<p>When the iPad announcement came out, I&#8217;ll admit I was thrilled about popovers. Those are those little bubbles that act like temporary panels when you press some button to summon them up.</p>
<p>A couple weeks earlier I&#8217;d used MAAttachedWindow to implement popovers in my app. In several places, the previous version of the app needed to use a sheet to present a more detailed view. That&#8217;s a lousy thing to do unless it&#8217;s really required. The user has to shift their focus, deal with a modal dialog, and then remember what they were doing.</p>
<p style="text-align: center;"><img style="border: 0px initial initial;" title="Old Modal.png" src="http://codehackers.net/blog/wp-content/uploads/2010/05/Old-Modal.png" border="0" alt="Old Modal.png" width="463" height="268" />﻿</p>
<p style="text-align: center;"><em>An old modal sheet used to edit the billing address on an invoice</em></p>
<p style="text-align: left;">With a popover the user sees details immediately related to what they&#8217;re working on without changing their focus. Clicking away from the dialog immediately dismisses it. When their attention shifts to another part of the document, they don&#8217;t need to perform the initial manual step of dismissing what they were previously working on.</p>
<p style="text-align: left;"><img title="popover.png" src="http://codehackers.net/blog/wp-content/uploads/2010/05/popover.png" border="0" alt="popover.png" width="600" height="180" /></p>
<p style="text-align: center;"><em>A new popover, displaying the same information, but in a way that doesn&#8217;t break the users workflow.</em></p>
<p style="text-align: left;">All in all, these work great on the desktop. They let me get rid of at least a half dozen modal sheets.</p>
<p style="text-align: left;">That being said, during initial testing, I found that users were confused by the lack of &#8216;Ok&#8217; and &#8216;Cancel&#8217; buttons on the popovers. Clicking elsewhere to dismiss it wasn&#8217;t an intuitive action, though they didn&#8217;t expect to have to dismiss the popovers when switching focus to another task. I added &#8216;Done&#8217; and &#8216;Cancel&#8217; buttons to my popovers. This increased the size of the popover, but provided the user with an immediate cue for how to dismiss them.</p>
<p><strong><span style="font-weight: normal;"> </span></strong></p>
<p><strong> </strong></p>
<p><strong></p>
<hr />
<div><span style="font-weight: bold;">Modal Popovers with Lightboxing</span></div>
<div><span style="font-weight: bold;"><br /></span></div>
<div><span style="font-weight: bold;"><span style="font-weight: normal;">Flush with popover success, I decided to try applying the same style to modal sheets.  I&#8217;ve seen this in a few web apps, and on the iPad too if I&#8217;m not mistaken (I might be, we don&#8217;t get them in Canada for a while yet).</span></span></div>
<p></strong></p>
<p>When I was experimenting, one of the big problems was that they weren&#8217;t very visible against the app.  There was no real way of indicating that they were modal.</p>
<div>
<p>Lightboxes are something you see a lot in the web world.  In order to highlight the modal popover, I dimmed the window they were modal to.  Though it helped draw attention to them, in my implementation it disabled interaction with the window below it.</p>
</div>
<div style="text-align: center;"><img title="Screen shot 2010-05-09 at 5.18.26 PM.png" src="http://codehackers.net/blog/wp-content/uploads/2010/05/Screen-shot-2010-05-09-at-5.18.26-PM1.png" border="0" alt="Screen shot 2010-05-09 at 5.18.26 PM.png" width="600" height="344" /></div>
<div style="text-align: center;"><em>A modal popover on a lightboxed background.</em></div>
<div style="text-align: center;"><em><br /></em></div>
<div>Feedback during beta testing was that they were just weird.  I got rid of these and replaced them with sheets.</div>
<p>That being said, I&#8217;m convinced that these help an application look more visually balanced, and it&#8217;s just a matter of getting the implementation right.  I plan on revisiting this at some point.</p>
<p><span style="font-weight: bold;"></p>
<hr />
</span></p>
<p><span style="font-weight: bold;">Nag Screens in the Sidebar</span></p>
<p>There&#8217;s a fine line between annoying your users with nag screens and not getting paid for your software.  In Stone Hill, I decided to try a bit of a different way of walking that line.</p>
<p>The nagsceen is unobtrusive.  In unregistered copies, there&#8217;s a couple of items in the source list: &#8220;Buy Stone Hill Invoicer&#8221; and &#8220;Register Stone Hill Invoicer&#8221;.  Clicking on the &#8220;Buy Stone Hill Invoicer&#8221; item shows a decent sized sales pitch.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Purchase Screen.png" src="http://codehackers.net/blog/wp-content/uploads/2010/05/Purchase-Screen.png" border="0" alt="Purchase Screen" width="600" height="352" /></p>
<p style="text-align: center;"><em>The &#8216;upgrade nag screen&#8217;.  This only shows when you click the &#8220;Buy Stone Hill Invoicer&#8221; item in the sourcelist.</em></p>
<p style="text-align: left;">During beta testing, one of my users asked where the purchase button was.  He&#8217;d checked under the application menu and couldn&#8217;t find it.  Fair enough.  I ended up adding a menu item that shows the same screen under the application menu.</p>
<p style="text-align: left;">This strikes me as being in the same vein as Panic&#8217;s top&#8211;of-the-window nag counters.</p>
<p><span style="font-weight: bold;"> </span></p>
<hr />
<p> </p>
<p><strong>Sidebar Search via the Global Search Box</strong></p>
<p>One of the things that always drove me nuts about Stone Hill was that the search function only worked on some screens.  In version two, using the search from one of the document screens filters the customer and inventory lists.  Though I considered creating a special iPhone style search box at the top of each table that would initially be scrolled out of view, it seems like a better idea to keep the global search box as the only place to search from.</p>
<p>Feedback has been positive about this so far, but this method may have discoverability issues.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Search.png" src="http://codehackers.net/blog/wp-content/uploads/2010/05/Search.png" border="0" alt="Search" width="264" height="324" /></p>
<p style="text-align: center;"><em>A customer list filtered by search text</em></p>
]]></content:encoded>
			<wfw:commentRss>http://codehackers.net/blog/?feed=rss2&amp;p=96</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Code Snippet: Finding a Router&#8217;s Name and MAC Address</title>
		<link>http://codehackers.net/blog/?p=82</link>
		<comments>http://codehackers.net/blog/?p=82#comments</comments>
		<pubDate>Sun, 14 Mar 2010 06:26:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://codehackers.net/blog/?p=82</guid>
		<description><![CDATA[Overview
	A couple years ago I blogged about some code that I use in Locations to find a routers name and MAC address.  A recent bug report brought that code back to my attention.  I&#8217;d made a couple of assumptions, like assuming that en0 was always ethernet, and not being able to detect when [...]]]></description>
			<content:encoded><![CDATA[<p><b>Overview</b></p>
<p>	A couple years ago <a href="http://codehackers.net/blog/?p=15">I blogged about some code that I use in Locations to find a routers name and MAC address</a>.  A recent bug report brought that code back to my attention.  I&#8217;d made a couple of assumptions, like assuming that en0 was always ethernet, and not being able to detect when the user was on a VPN.  Skip down a bit to find the updated code.</p>
<p>	The resulting code takes less resources, is more robust, and is shorter.  This is definitely a case of looking back at my code and wondering &#8220;<a href="http://inessential.com/2009/07/17/on_that_moron_feeling">What moron wrote this?</a>&#8221;  It&#8217;s a wonderful feeling.</p>
<p><b>Code &#8211; Finding the Router&#8217;s MAC Address</b></p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; ">+ (<span style="color:#400080;">NSString</span> *) <span style="color:#6c0540;">primaryRoutersMACAddress</span> {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSMutableString</span> *MACAddress = [<span style="color:#400080;">NSMutableString</span> <span style="color:#6c0540;">string</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Figure out which interface we&#8217;re using<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;SCDynamicStoreRef theDynamicStore = <span style="color:#003369;">SCDynamicStoreCreate</span>(<span style="color:#881350;">nil</span>, <span style="color:#003369;">CFSTR</span>(<span style="color:#760f15;">&quot;FindCurrentInterfaceAndIP&quot;</span>), <span style="color:#881350;">nil</span>, <span style="color:#881350;">nil</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;CFDictionaryRef returnedPList = <span style="color:#003369;">SCDynamicStoreCopyValue</span>(theDynamicStore, <span style="color:#003369;">CFSTR</span>(<span style="color:#760f15;">&quot;com.apple.network.identification&quot;</span>));<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">CFRelease</span>(theDynamicStore);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>([(<span style="color:#400080;">NSDictionary</span> *)returnedPList <span style="color:#6c0540;">valueForKey:</span><span style="color:#760f15;">@&quot;ActiveIdentifiers&quot;</span>] != <span style="color:#881350;">nil</span>) { <span style="color:#236e25;">// We have a network<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSString</span> *activeIdentifier = [[(<span style="color:#400080;">NSDictionary</span> *)returnedPList <span style="color:#6c0540;">valueForKey:</span><span style="color:#760f15;">@&quot;ActiveIdentifiers&quot;</span>] <span style="color:#6c0540;">lastObject</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSArray</span> *identifierParts = [activeIdentifier <span style="color:#6c0540;">componentsSeparatedByString:</span><span style="color:#760f15;">@&quot;=&quot;</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[MACAddress <span style="color:#6c0540;">setString:</span>[identifierParts <span style="color:#6c0540;">lastObject</span>]];<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> MACAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
}
</div>
<p><b>Code &#8211; Finding the Router&#8217;s SSID</b></p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; ">+ (<span style="color:#400080;">NSString</span> *) <span style="color:#6c0540;">primaryRoutersSSID</span> {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSMutableString</span> *interfaceName = [<span style="color:#400080;">NSMutableString</span> <span style="color:#6c0540;">string</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Figure out if we&#8217;ve only got the one network identifier, or if there&#8217;s several<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// If there&#8217;s several, we&#8217;re on a VPN or something<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// In that case, we&#8217;ll just use the servername as the interface name<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;SCDynamicStoreRef theDynamicStore = <span style="color:#003369;">SCDynamicStoreCreate</span>(<span style="color:#881350;">nil</span>, <span style="color:#003369;">CFSTR</span>(<span style="color:#760f15;">&quot;FindCurrentInterfaceAndIP&quot;</span>), <span style="color:#881350;">nil</span>, <span style="color:#881350;">nil</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;CFDictionaryRef networkIdentification = <span style="color:#003369;">SCDynamicStoreCopyValue</span>(theDynamicStore, <span style="color:#003369;">CFSTR</span>(<span style="color:#760f15;">&quot;com.apple.network.identification&quot;</span>));<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">CFRelease</span>(theDynamicStore);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>([[(<span style="color:#400080;">NSDictionary</span> *)networkIdentification <span style="color:#6c0540;">valueForKey:</span><span style="color:#760f15;">@&quot;ActiveIdentifiers&quot;</span>] <span style="color:#6c0540;">count</span>] &gt; <span style="color:#0000ff;">1</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSString</span> *activeIdentifier = [[(<span style="color:#400080;">NSDictionary</span> *)networkIdentification <span style="color:#6c0540;">valueForKey:</span><span style="color:#760f15;">@&quot;ActiveIdentifiers&quot;</span>] <span style="color:#6c0540;">lastObject</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSArray</span> *identifierParts = [activeIdentifier <span style="color:#6c0540;">componentsSeparatedByString:</span><span style="color:#760f15;">@&quot;=&quot;</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[interfaceName <span style="color:#6c0540;">setString:</span>[identifierParts <span style="color:#6c0540;">lastObject</span>]];<br />
&nbsp;&nbsp;&nbsp;&nbsp;} <span style="color:#881350;">else</span> {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Check the primary interface name<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SCDynamicStoreRef theDynamicStore = <span style="color:#003369;">SCDynamicStoreCreate</span>(<span style="color:#881350;">nil</span>, <span style="color:#003369;">CFSTR</span>(<span style="color:#760f15;">&quot;FindCurrentInterfaceAndIP&quot;</span>), <span style="color:#881350;">nil</span>, <span style="color:#881350;">nil</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CFDictionaryRef interfacePlist = <span style="color:#003369;">SCDynamicStoreCopyValue</span>(theDynamicStore, <span style="color:#003369;">CFSTR</span>(<span style="color:#760f15;">&quot;State:/Network/Global/IPv4&quot;</span>));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSString</span> *enX = [(<span style="color:#400080;">NSDictionary</span> *)interfacePlist <span style="color:#6c0540;">valueForKey:</span><span style="color:#760f15;">@&quot;PrimaryInterface&quot;</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Find if there&#8217;s an airport entry for that interface<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSString</span> *airportPath = [<span style="color:#400080;">NSString</span> <span style="color:#6c0540;">stringWithFormat:</span><span style="color:#760f15;">@&quot;State:/Network/Interface/%@/AirPort&quot;</span>, <span style="color:#6c0540;">enX</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CFDictionaryRef airportPlist = <span style="color:#003369;">SCDynamicStoreCopyValue</span>(theDynamicStore, (CFStringRef)airportPath);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(airportPlist != <span style="color:#881350;">nil</span>) { <span style="color:#236e25;">// If there is, grab the SSID<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>([(<span style="color:#400080;">NSDictionary</span> *)airportPlist <span style="color:#6c0540;">valueForKey:</span><span style="color:#760f15;">@&quot;SSID_STR&quot;</span>] != <span style="color:#881350;">nil</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[interfaceName <span style="color:#6c0540;">setString:</span>[(<span style="color:#400080;">NSDictionary</span> *)airportPlist <span style="color:#6c0540;">valueForKey:</span><span style="color:#760f15;">@&quot;SSID_STR&quot;</span>]];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <span style="color:#881350;">else</span> <span style="color:#881350;">if</span><span style="color:#003369;"> </span>([(<span style="color:#400080;">NSDictionary</span> *)airportPlist <span style="color:#6c0540;">valueForKey:</span><span style="color:#760f15;">@&quot;SSID&quot;</span>] != <span style="color:#881350;">nil</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[interfaceName <span style="color:#6c0540;">setString:</span>[(<span style="color:#400080;">NSDictionary</span> *)airportPlist <span style="color:#6c0540;">valueForKey:</span><span style="color:#760f15;">@&quot;SSID&quot;</span>]];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <span style="color:#881350;">else</span> {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[interfaceName <span style="color:#6c0540;">setString:</span><span style="color:#760f15;">@&quot;Wireless Network&quot;</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <span style="color:#881350;">else</span> { <span style="color:#236e25;">// Otherwise, return &#8216;Wired Network&#8217;<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[interfaceName <span style="color:#6c0540;">setString:</span><span style="color:#760f15;">@&quot;Wired Network&quot;</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Figure out which interface we&#8217;re using<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> interfaceName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
}
</div>
<p><b>Attribution</b><br />
All source is released free of charge. You may incorporate it into any of your applications. I assume no liability for any action that may come from you using this source. If you do use this in your application, I&#8217;d like a mention in your about box, but I don&#8217;t require it.  Don&#8217;t forget to drop me an email at <a href="mailto:warwick@codehackers.net">warwick@codehackers.net</a> so I know when to stroke my ego.</p>
]]></content:encoded>
			<wfw:commentRss>http://codehackers.net/blog/?feed=rss2&amp;p=82</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Feel the Beat&#8221;</title>
		<link>http://codehackers.net/blog/?p=71</link>
		<comments>http://codehackers.net/blog/?p=71#comments</comments>
		<pubDate>Fri, 18 Dec 2009 05:57:53 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://codehackers.net/blog/?p=71</guid>
		<description><![CDATA[It&#8217;s been a busy semester but luckily, one of the (weirdest) things about being a student is that my projects actually have an ending.  Earlier this week I helped finish up a project for my music information retrieval class.  Here&#8217;s what we&#8217;ve been working on.

When I was a kid, I wanted to be [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a busy semester but luckily, one of the (weirdest) things about being a student is that my projects actually have an ending.  Earlier this week I helped finish up a project for my music information retrieval class.  Here&#8217;s what we&#8217;ve been working on.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube-nocookie.com/v/69MNgR-QdfI&amp;hl=en_US&amp;fs=1&amp;rel=0" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="505" src="http://www.youtube-nocookie.com/v/69MNgR-QdfI&amp;hl=en_US&amp;fs=1&amp;rel=0" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>When I was a kid, I wanted to be either a toy inventor or a writer.  These days I&#8217;m lucky enough to be someone who writes toys.</p>
]]></content:encoded>
			<wfw:commentRss>http://codehackers.net/blog/?feed=rss2&amp;p=71</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Code Snippet: Better Table Support in NSTextView</title>
		<link>http://codehackers.net/blog/?p=70</link>
		<comments>http://codehackers.net/blog/?p=70#comments</comments>
		<pubDate>Sun, 31 May 2009 09:49:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://codehackers.net/blog/?p=70</guid>
		<description><![CDATA[
Overview

	I&#8217;m working on Stone Hill Invoicer, adding some new functionality to the .rtfd editor where users can customize how their invoices print.  One of the support emails that pops up once in a while is asking why it&#8217;s so hard to add and delete columns to tables.  Until now, I&#8217;ve just been using [...]]]></description>
			<content:encoded><![CDATA[<p />
<b>Overview</b></p>
<p />
<p>	I&#8217;m working on Stone Hill Invoicer, adding some new functionality to the .rtfd editor where users can customize how their invoices print.  One of the support emails that pops up once in a while is asking why it&#8217;s so hard to add and delete columns to tables.  Until now, I&#8217;ve just been using a standard NSTextView, so I&#8217;ve been apologetic and put it on my list of things to take care of for 2.0.</p>
<p>	This post presents some code for a subclass which add in additional contextual menu items to the standard NSTextView menu when over a table.  Here are the old and new menus for comparison:</p>
<table border="0" width="100%">
<tr>
<td valign="top">
<div style="text-align:center;"><img src="http://codehackers.net/blog/wp-content/uploads/2009/05/picture-2.png" alt="Picture 2.png" border="0" width="264" height="318" /></div>
</td>
<td valign="top">
<div style="text-align:center;"><img src="http://codehackers.net/blog/wp-content/uploads/2009/05/picture-5.png" alt="Picture 5.png" border="0" width="264" height="468" /></div>
</td>
</tr>
</table>
<p />
<p><b>Download</b></p>
<p />
If you&#8217;d like to use this subclass, download the <a href="http://www.codehackers.net/blog/wp-content/uploads/2009/05/CHTextView.h">header</a> and <a href="http://www.codehackers.net/blog/wp-content/uploads/2009/05/CHTextView.m">implementation</a> files and integrate them into your project.  Remember to select your NSTextView in interface builder and change it to a CHTextView.</p>
<p />
<b>Attribution</b><br />
All source is released free of charge. You may incorporate it into any of your applications. I assume no liability for any action that may come from you using this source. If you do use this in your application, I&#8217;d like a mention in your about box, but I don&#8217;t require it.  Don&#8217;t forget to drop me an email at <a href="mailto:warwick@codehackers.net">warwick@codehackers.net</a> so I know when to stroke my ego.</p>
]]></content:encoded>
			<wfw:commentRss>http://codehackers.net/blog/?feed=rss2&amp;p=70</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Links For Adding Applescript to Your Cocoa App</title>
		<link>http://codehackers.net/blog/?p=66</link>
		<comments>http://codehackers.net/blog/?p=66#comments</comments>
		<pubDate>Sat, 28 Jun 2008 22:53:10 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://codehackers.net/blog/?p=66</guid>
		<description><![CDATA[Looking to implement some basic Applescript support on my application, I was somewhat at a loss where to start.  Here are some links I found useful.  If you know of any other Applescript resources that helped you out, don&#8217;t be shy about dropping a link in the comments!
Cocoa Scripting Guide
An in-depth look at [...]]]></description>
			<content:encoded><![CDATA[<p>Looking to implement some basic Applescript support on my application, I was somewhat at a loss where to start.  Here are some links I found useful.  If you know of any other Applescript resources that helped you out, don&#8217;t be shy about dropping a link in the comments!</p>
<p><a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ScriptableCocoaApplications/SApps_intro/chapter_1_section_1.html#//apple_ref/doc/uid/TP40001982-BCICHGIE"><b>Cocoa Scripting Guide</b></a></p>
<p>An in-depth look at how scripting works from a conceptual level.  A long read, but worth it.</p>
<p><a href="http://developer.apple.com/samplecode/SimpleScriptingProperties/"><b>Simple Scripting Properties</b></a></p>
<p>A simple example for XCode 3 and Leopard which shows a small Applescript implementation that actually works.  Excellent to tear apart and learn from.</p>
<p><a href="http://developer.apple.com/releasenotes/AppleScript/ASTerminology_AppleEventCodes/TermsAndCodes.html"><b>Applescript Terminology and Apple Event Codes</b></a></p>
<p>Lists Applescript terminology and associated codes.</p>
]]></content:encoded>
			<wfw:commentRss>http://codehackers.net/blog/?feed=rss2&amp;p=66</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Code Snippet: Get Playlist Names From iTunes</title>
		<link>http://codehackers.net/blog/?p=65</link>
		<comments>http://codehackers.net/blog/?p=65#comments</comments>
		<pubDate>Mon, 02 Jun 2008 17:46:21 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://codehackers.net/blog/?p=65</guid>
		<description><![CDATA[	I&#8217;m working on Locations Pro and adding some new actions.  One action I&#8217;m adding is &#8216;Play an iTunes Playlist&#8217;.  Obviously I need to know what the playlists are so that I can present the user with a nice list to choose from.
	If you need to retrieve library information from iTunes there are a [...]]]></description>
			<content:encoded><![CDATA[<p>	I&#8217;m working on <a href="http://www.codehackers.net/locations">Locations Pro</a> and adding some new actions.  One action I&#8217;m adding is &#8216;Play an iTunes Playlist&#8217;.  Obviously I need to know what the playlists are so that I can present the user with a nice list to choose from.</p>
<p>	If you need to retrieve library information from iTunes there are a couple ways to do it.  You can make a request via Applescript but that requires iTunes to be open.  Alternately you can use the &#8220;iTunes Music Library.xml&#8221; file.  Below is a method I put together this morning to do that.</p>
<p>	While I was putting this together, I came across a <a href="http://jay.tuley.name/archives/2005/03/10/iTunes-Music-Library.xml">link from Jay Tuley</a>.  He pointed out that the the library xml file has two possible locations that you have to account for.</p>
<p>	He also make a quick reference to the occasional user doing fun things with Finder aliases and moving that XML file.  Why you&#8217;d want to move that file, I&#8217;ve got no idea.  I do know that this morning I had no idea how to resolve an alias or do anything with FSRefs.  Now I know a little more.  The iTunes related code calls a second little function I put together which returns an NSURL with the aliases resolved given a POSIX path.</p>
<p>Enough talking.  Here&#8217;s the code:</p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; ">- (<span style="color:#400080;">NSArray</span> *) <span style="color:#6c0540;">iTunesPlaylistNames</span> {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSMutableArray</span> *playlistNames = [<span style="color:#400080;">NSMutableArray</span> <span style="color:#6c0540;">array</span>];</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSURL</span> *libraryURL;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSString</span> *normalLibraryPath = [<span style="color:#760f15;">@&quot;~/Music/iTunes/iTunes Music Library.xml&quot;</span> <span style="color:#6c0540;">stringByExpandingTildeInPath</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSString</span> *olderLibraryPath = [<span style="color:#760f15;">@&quot;~/Documents/iTunes/iTunes Music Library.xml&quot;</span> <span style="color:#6c0540;">stringByExpandingTildeInPath</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>([[<span style="color:#400080;">NSFileManager</span> <span style="color:#6c0540;">defaultManager</span>] <span style="color:#6c0540;">fileExistsAtPath:</span>normalLibraryPath]) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libraryURL = [<span style="color:#881350;">self</span> <span style="color:#6c0540;">resolvedFileURLWithPath:</span>normalLibraryPath];<br />
&nbsp;&nbsp;&nbsp;&nbsp;} <span style="color:#881350;">else</span> <span style="color:#881350;">if</span><span style="color:#003369;"> </span>([[<span style="color:#400080;">NSFileManager</span> <span style="color:#6c0540;">defaultManager</span>] <span style="color:#6c0540;">fileExistsAtPath:</span>olderLibraryPath]) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libraryURL = [<span style="color:#881350;">self</span> <span style="color:#6c0540;">resolvedFileURLWithPath:</span>olderLibraryPath];<br />
&nbsp;&nbsp;&nbsp;&nbsp;} <span style="color:#881350;">else</span> {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libraryURL = <span style="color:#881350;">nil</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(libraryURL != <span style="color:#881350;">nil</span>) { <span style="color:#236e25;">// If an iTunes Library was found<br />
</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSDictionary</span> *libraryDictionary = [<span style="color:#400080;">NSDictionary</span> <span style="color:#6c0540;">dictionaryWithContentsOfURL:</span>libraryURL];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSArray</span> *playlists = [libraryDictionary <span style="color:#6c0540;">objectForKey:</span><span style="color:#760f15;">@&quot;Playlists&quot;</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">int</span> i=<span style="color:#0000ff;">0</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">for</span><span style="color:#003369;"> </span>(i=<span style="color:#0000ff;">0</span>; i&lt;[playlists <span style="color:#6c0540;">count</span>]; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(![[playlists <span style="color:#6c0540;">objectAtIndex:</span>i] <span style="color:#6c0540;">objectForKey:</span><span style="color:#760f15;">@&quot;Visible&quot;</span>]) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>([[playlists <span style="color:#6c0540;">objectAtIndex:</span>i] <span style="color:#6c0540;">objectForKey:</span><span style="color:#760f15;">@&quot;Name&quot;</span>]) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[playlistNames <span style="color:#6c0540;">addObject:</span>[[playlists <span style="color:#6c0540;">objectAtIndex:</span>i] <span style="color:#6c0540;">objectForKey:</span><span style="color:#760f15;">@&quot;Name&quot;</span>]];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> playlistNames;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
}</p>
<p>- (<span style="color:#400080;">NSURL</span> *) <span style="color:#6c0540;">resolvedFileURLWithPath:</span>(<span style="color:#400080;">NSString</span> *)path {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;CFURLRef url = <span style="color:#003369;">CFURLCreateWithFileSystemPath</span>(kCFAllocatorDefault, (CFStringRef)path, kCFURLPOSIXPathStyle, <span style="color:#881350;">NO</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSString</span> *resolvedPath;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(url != <span style="color:#881350;">NULL</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FSRef fsRef;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(<span style="color:#003369;">CFURLGetFSRef</span>(url, &amp;fsRef)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Boolean targetIsFolder, wasAliased;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">FSResolveAliasFile </span>(&amp;fsRef, true, &amp;targetIsFolder, &amp;wasAliased);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CFURLRef resolvedUrl = <span style="color:#003369;">CFURLCreateFromFSRef</span>(kCFAllocatorDefault, &amp;fsRef);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(resolvedUrl != <span style="color:#881350;">NULL</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resolvedPath = [<span style="color:#400080;">NSString</span> <span style="color:#6c0540;">stringWithString:</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color:#400080;">NSString</span> *)<span style="color:#003369;">CFURLCopyFileSystemPath</span>(resolvedUrl, kCFURLPOSIXPathStyle)];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">CFRelease</span>(resolvedUrl);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">CFRelease</span>(url);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(resolvedPath != <span style="color:#881350;">nil</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#400080;">NSURL</span> *resolvedURL = [<span style="color:#400080;">NSURL</span> <span style="color:#6c0540;">fileURLWithPath:</span>resolvedPath];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> resolvedURL;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> <span style="color:#881350;">nil</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
}
</div>
<p>Edit: As always, go ahead and use the code however you want, commercially or otherwise.  I don&#8217;t mind a mention in your about box (and an email if I get one), but I don&#8217;t require it.</p>
]]></content:encoded>
			<wfw:commentRss>http://codehackers.net/blog/?feed=rss2&amp;p=65</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Prototype Mode</title>
		<link>http://codehackers.net/blog/?p=63</link>
		<comments>http://codehackers.net/blog/?p=63#comments</comments>
		<pubDate>Sat, 31 May 2008 12:57:02 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://codehackers.net/blog/?p=63</guid>
		<description><![CDATA[	If you&#8217;re a developer you&#8217;ve probably fallen prey at some point.  You start on a new project and it flies together faster than you can say &#8220;good coding practice&#8221;.  Do you keep running while the idea is fresh?  Do you stop and make your code maintainable?  I usually keep running.
	I just [...]]]></description>
			<content:encoded><![CDATA[<p>	If you&#8217;re a developer you&#8217;ve probably fallen prey at some point.  You start on a new project and it flies together faster than you can say &#8220;good coding practice&#8221;.  Do you keep running while the idea is fresh?  Do you stop and make your code maintainable?  I usually keep running.</p>
<p>	I just finished a large update to one of my apps.  It&#8217;s only 8000 lines of code, but quick coding and late night enthusiasm had compressed it into a few poorly thought out classes.  Adding features was criminal.  When I decided to streamline the UI, I started with a clean project and brought code over.  Sometimes the only way to clean house is to move.</p>
<p>	Prototype mode is a sweet place to be.  My favourite features are born here.  I can&#8217;t rid myself of it, but I have come up with a few strategies to help mitigate the damage.</p>
<p>	<b>Be Inspired Somewhere Else</b></p>
<p>	I prototype in Interface Builder, sprinkling code as needed.  If I add to my current project I take shortcuts to see results quicker.  Building in another project means that I&#8217;ll integrate it later.  By that time, I&#8217;m ready to listen to the better angels of my nature.</p>
<p>	<b>Use Plugins When Applicable</b></p>
<p>	When I started writing Locations Pro I decided to make every action it&#8217;s own plugin.  Using bundles forced me to think my API through, giving each bundle a common structure.  It also kept my code isolated in smaller blocks which were less daunting to clean up.</p>
<p>	<b>Get Rolling With Cleanup</b></p>
<p>	My biggest problem with getting started in the morning is the part where I actually get started.  If I don&#8217;t slip right into it I find my day devolves into staring at an empty NetNewsWire.  Starting with little cleanup tasks gets me rolling.  The side effect is better code.</p>
]]></content:encoded>
			<wfw:commentRss>http://codehackers.net/blog/?feed=rss2&amp;p=63</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Appeal of Twitter</title>
		<link>http://codehackers.net/blog/?p=60</link>
		<comments>http://codehackers.net/blog/?p=60#comments</comments>
		<pubDate>Sat, 12 Apr 2008 03:40:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://codehackers.net/blog/?p=60</guid>
		<description><![CDATA[Twitter is like getting instant messages from the people you wish you knew.
]]></description>
			<content:encoded><![CDATA[<p>Twitter is like getting instant messages from the people you wish you knew.</p>
]]></content:encoded>
			<wfw:commentRss>http://codehackers.net/blog/?feed=rss2&amp;p=60</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
