<?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>Jeff Kelley’s Blog &#187; programming</title>
	<atom:link href="http://blog.slaunchaman.com/tag/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.slaunchaman.com</link>
	<description>Mac tips, iPhone applications, and the like</description>
	<lastBuildDate>Fri, 02 Dec 2011 04:51:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Enforcing iOS Security Settings in Third-Party Applications</title>
		<link>http://blog.slaunchaman.com/2011/12/01/enforcing-ios-security-settings-in-third-party-applications/</link>
		<comments>http://blog.slaunchaman.com/2011/12/01/enforcing-ios-security-settings-in-third-party-applications/#comments</comments>
		<pubDate>Fri, 02 Dec 2011 04:51:07 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[iOS Programming]]></category>
		<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[configuration profiles]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[OpenSSL]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=478</guid>
		<description><![CDATA[A while back, I was working on an  application for a client with a very specific requirement. Since it collected personal data, the application could only run on iOS devices that were protected with a passcode. This requirement, seemingly very simple from the client’s perspective, was a bit of a hassle to implement on the [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, I was working on an  application for a client with a very specific requirement. Since it collected personal data, the application could only run on iOS devices that were protected with a passcode. This requirement, seemingly very simple from the client’s perspective, was a bit of a hassle to implement on the programming side of things. There’s no simple method on <code>UIDevice</code> to determine if a passcode is set, nor is there a way to force that programatically. In fact, there’s no way to force most things like that. The iOS device isn’t the programmer’s, it’s the user’s. Except when it isn’t.</p>
<p>One of the things that you <em>can</em> do is to use the <a title="Apple - Support - iPhone - Enterprise" href="http://www.apple.com/support/iphone/enterprise/">iPhone Configuration Utility</a> to make a configuration profile. These profiles can support a range of things, from requiring a passcode (or even an advanced, non-numeric passcode) to WiFi settings, VPN to CardDAV settings. Creating a configuration profile that requires a passcode, then installing that configuration profile onto the device is a no-brainer. But how do you ensure that the application will only run in that case?</p>
<p><strong>Disclaimer:</strong> Before I go any further, you should know that since this was an in-house project, none of the code that I wrote made it into the App Store. Therefore, I don’t know if this is kosher in an App Store app, nor do I recommend this approach for that.</p>
<p>One thing that you <em>can</em> do is to include a self-signed certificate in a configuration profile. Those of you familiar with OpenSSL may be groaning as you realize where this horrible, horrible workaround is headed. I created a new certificate authority. With that new certificate authority, I signed a separate certificate that I had created. Verifying this certificate, then, requires that the verifying party accept the certificate authority’s certificate as valid. Well, since you can set that in the configuration profile, I did, along with the passcode requirement. Then, in the app, I bundled the certificate that I had signed with my CA.</p>
<p>When the app starts up, it attempts to verify the certificate. In the case where the configuration profile is installed and the CA’s certificate is in the system’s keychain as trusted, this is no problem: the certificate checks out and my app is free to go. If that validation fails, however, then I know that the certificate from the CA is in the system, so I know that the configuration profile is installed, as well.</p>
<p>Why this works for a passcode so well is that to install a configuration profile on a device without a passcode when the profile requires one is that <em>you can’t install it without setting a passcode in the process.</em> For the client, this was Good Enough, and the app shipped and worked properly. It’s worth noting, though, that the less the end-user knows about this process, the better. To circumvent the passcode restriction, all one would have to do would be to modify the configuration profile to still include the CA’s certificate, but <em>not</em> the pas code requirement. For that reason I can’t recommend this for anything like EMR or tax records, but for minor demographic information like we were collecting, this sufficed.</p>
<p>I realize this didn’t include any code, but the individual portions aren’t that hard, and I don’t have access to the original code so I’d have to re-write them all. Here they are in a nicely-formatted list for those keeping score at home:</p>
<ol>
<li>Create a new certificate authority with OpenSSL.</li>
<li>Create a new certificate, then sign it with that certificate authority you just created.</li>
<li>Create a configuration profile in the iTunes Configuration Utility with the settings you would like to enforce.</li>
<li>In the “Credentials” section in the iTunes Configuration Utility, add your CA’s public-facing certificate to the configuration profile.</li>
<li>Add the certificate you signed with your CA to your application’s bundle.</li>
<li>In your application, verify the certificate you included.</li>
<li>Distribute the configuration profile along with your application to end users.</li>
</ol>
<p>Like I said, this is far from perfect. But when you’re working with an enterprise client who has Big Needs, this is one trick to keep in your back pocket when you’re up against a deadline.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2011/12/01/enforcing-ios-security-settings-in-third-party-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cocoa Touch: Circumventing UITableViewCell Redraw Issues with Multithreading</title>
		<link>http://blog.slaunchaman.com/2011/08/14/cocoa-touch-circumventing-uitableviewcell-redraw-issues-with-multithreading/</link>
		<comments>http://blog.slaunchaman.com/2011/08/14/cocoa-touch-circumventing-uitableviewcell-redraw-issues-with-multithreading/#comments</comments>
		<pubDate>Sun, 14 Aug 2011 20:14:23 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[iOS Programming]]></category>
		<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[multithreading]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[UITableViewCell]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=467</guid>
		<description><![CDATA[In your career as a Cocoa or Cocoa Touch developer, every now and then you’ll encounter an issue with something Apple has written. Whether it’s a full-blown bug, something that doesn’t work quite how you’d expect it to, or a minor inconvenience, it happens. When it does, naturally the first thing you do is file [...]]]></description>
			<content:encoded><![CDATA[<p>In your career as a Cocoa or Cocoa Touch developer, every now and then you’ll encounter an issue with something Apple has written. Whether it’s a full-blown bug, something that doesn’t work quite how you’d expect it to, or a minor inconvenience, it happens. When it does, naturally the first thing you do is file <a href="http://bugreport.apple.com">a bug report</a> (<em>right?</em>). After that, though, you need to <em>do something</em> about it. This usually occurs right when a project is due, so often we can’t wait for Apple’s engineering teams to fix the problems (or tell you that you’re wrong). This post is an example of using KVO to get around the problem without worrying about it anymore.</p>
<p><strong>The Problem:</strong> In iOS, if you create a <code>UITableViewCell</code> and return it to the table view in its data source’s <code>-tableView:cellForRowAtIndexPath:</code> method, but then return later (say, after doing some background processing) to add an image to the cell’s <code>imageView</code>, you don’t see anything! Why? Well, it looks like either the image view isn’t added to the cell’s view hierarchy if you don’t immediately add an image or there’s some other bug in the <code>UITableViewCell</code> implementation. I don’t think it’s a bug, I think it’s just a side effect of an optimization; if there’s no image, why add it to the cell?</p>
<p>So how do we fix it? Well, a simple call to <code>-setNeedsLayout</code> gets the cell to fix itself quite nicely. But we shouldn’t have to do that from our table view data source—that has a bit of code smell to it. Lines like that quickly get overused, with programmers calmly stating, “I don’t know why, but we always do that.” No, a better solution is to get the cell to handle this problem on its own.</p>
<p>We’ll create a subclass of UITableViewCell and use KVO. When we create the cell, we’ll register for KVO notifications with the on the image view whenever its <code>image</code> property is modified—but we’ll send the option to include the <em>old</em> value in the change dictionary. When we receive the notification, we’ll look at that dictionary, and if the old value was <code>nil</code>, then we’ll send <code>self</code> a <code>-setNeedsLayout</code> message. This avoids having to do it in other classes, and only does it when necessary. We simply set it and forget it.</p>
<div id="gist-1143494" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">#import &lt;UIKit/UIKit.h&gt;</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="k">@interface</span> <span class="nc">JKTableViewCell</span> : <span class="nc">UITableViewCell</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'><span class="k">@end</span></div><div class='line' id='LC7'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1143494/a53db908610a1504ee6b7b9cc120fa0a39e68e0e/JKTableViewCell.h" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1143494#file_jk_table_view_cell.h" style="float:right;margin-right:10px;color:#666">JKTableViewCell.h</a>
            <a href="https://gist.github.com/1143494">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">#import &quot;JKTableViewCell.h&quot;</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="k">@implementation</span> <span class="nc">JKTableViewCell</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'><span class="k">-</span> <span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nf">initWithStyle:</span><span class="p">(</span><span class="n">UITableViewCellStyle</span><span class="p">)</span><span class="nv">style</span> <span class="nf">reuseIdentifier:</span><span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="nv">reuseIdentifier</span></div><div class='line' id='LC7'><span class="p">{</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">self</span> <span class="o">=</span> <span class="p">[</span><span class="n">super</span> <span class="nl">initWithStyle:</span><span class="n">style</span> <span class="nl">reuseIdentifier:</span><span class="n">reuseIdentifier</span><span class="p">];</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="n">self</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">[[</span><span class="n">self</span> <span class="n">imageView</span><span class="p">]</span> <span class="nl">addObserver:</span><span class="n">self</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nl">forKeyPath:</span><span class="s">@&quot;image&quot;</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nl">options:</span><span class="n">NSKeyValueObservingOptionOld</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nl">context:</span><span class="nb">NULL</span><span class="p">];</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">self</span><span class="p">;</span></div><div class='line' id='LC18'><span class="p">}</span></div><div class='line' id='LC19'><br/></div><div class='line' id='LC20'><span class="c1">// The reason we’re observing changes is that if you create a table view cell, return it to the</span></div><div class='line' id='LC21'><span class="c1">// table view, and then later add an image (perhaps after doing some background processing), you</span></div><div class='line' id='LC22'><span class="c1">// need to call -setNeedsLayout on the cell for it to add the image view to its view hierarchy. We</span></div><div class='line' id='LC23'><span class="c1">// asked the change dictionary to contain the old value because this only needs to happen if the</span></div><div class='line' id='LC24'><span class="c1">// image was previously nil.</span></div><div class='line' id='LC25'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">observeValueForKeyPath:</span><span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="nv">keyPath</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nf">ofObject:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nv">object</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nf">change:</span><span class="p">(</span><span class="n">NSDictionary</span> <span class="o">*</span><span class="p">)</span><span class="nv">change</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nf">context:</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="nv">context</span></div><div class='line' id='LC29'><span class="p">{</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="n">object</span> <span class="o">==</span> <span class="p">[</span><span class="n">self</span> <span class="n">imageView</span><span class="p">]</span> <span class="o">&amp;&amp;</span></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">[</span><span class="n">keyPath</span> <span class="nl">isEqualToString:</span><span class="s">@&quot;image&quot;</span><span class="p">]</span> <span class="o">&amp;&amp;</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">([</span><span class="n">change</span> <span class="nl">objectForKey:</span><span class="n">NSKeyValueChangeOldKey</span><span class="p">]</span> <span class="o">==</span> <span class="nb">nil</span> <span class="o">||</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">[</span><span class="n">change</span> <span class="nl">objectForKey:</span><span class="n">NSKeyValueChangeOldKey</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="n">NSNull</span> <span class="n">null</span><span class="p">]))</span> <span class="p">{</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">[</span><span class="n">self</span> <span class="n">setNeedsLayout</span><span class="p">];</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC36'><span class="p">}</span></div><div class='line' id='LC37'><br/></div><div class='line' id='LC38'><span class="k">@end</span></div><div class='line' id='LC39'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1143494/90294445f0b984f4f823911404a14dca57d652ad/JKTableViewCell.m" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1143494#file_jk_table_view_cell.m" style="float:right;margin-right:10px;color:#666">JKTableViewCell.m</a>
            <a href="https://gist.github.com/1143494">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2011/08/14/cocoa-touch-circumventing-uitableviewcell-redraw-issues-with-multithreading/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GCD Example Updated (Now With More Speed!)</title>
		<link>http://blog.slaunchaman.com/2011/08/12/gcd-example-updated-now-with-more-speed/</link>
		<comments>http://blog.slaunchaman.com/2011/08/12/gcd-example-updated-now-with-more-speed/#comments</comments>
		<pubDate>Sat, 13 Aug 2011 04:03:57 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[iOS Programming]]></category>
		<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[Grand Central Dispatch]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[meta]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[UIImage]]></category>
		<category><![CDATA[updates]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=463</guid>
		<description><![CDATA[Due to popular demand, I’ve updated my GCD example from previous talks to include a few things to make the example not only do something on a background queue, but also snappy. It should scroll much better now. A quick rundown of what changed: Images are now resized. Since the example uses wallpaper-sized images, there’s [...]]]></description>
			<content:encoded><![CDATA[<p>Due to popular demand, I’ve updated <a href="https://github.com/SlaunchaMan/GCDExample">my GCD example</a> from previous talks to include a few things to make the example not only do something on a background queue, but also snappy. It should scroll much better now. A quick rundown of what changed:</p>
<ul>
<li><strong>Images are now resized.</strong> Since the example uses wallpaper-sized images, there’s no sense in <em>not</em> resizing them to go on a 44-pixel-tall table view cell. I’m using the popular image-resizing routines from <a href="http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/" target="_blank">Trevor’s Bike Shed</a> to do the resizing with a nice interpolation quailty.</li>
<li><strong>Those resized images are now cached.</strong> I use an <code>NSCache</code> to store the images. If the app receives a memory warning, it’ll jettison all of the cached images, but if you’re just scrolling up and down this is a quick and dirty way to cache the images. I had never really used <code>NSCache</code> before, so this was a good excuse to try it.</li>
</ol>
<p>I’m at <a href="http://www.cocoaconf.com" target="_blank">CocoaConf</a> in that state down to the South today, so this post has been brought to you by late-night hotel room caffeine. I made some other changes to the project to deal with a weird table view cell bug that I’ve submitted to Apple; a post on that is coming up next!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2011/08/12/gcd-example-updated-now-with-more-speed/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>iOS Programming for Multicore Processors</title>
		<link>http://blog.slaunchaman.com/2011/03/03/ios-programming-for-multicore-processors/</link>
		<comments>http://blog.slaunchaman.com/2011/03/03/ios-programming-for-multicore-processors/#comments</comments>
		<pubDate>Fri, 04 Mar 2011 02:54:31 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Mac Programming]]></category>
		<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[Grand Central Dispatch]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[multithreading]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=417</guid>
		<description><![CDATA[With the impending release of the iPad 2, understanding how to program multithreaded applications will quickly become paramount as applications continue to push the envelope to make immersive experiences with high-performance computation. Now, without actually having a multicore iPad in my hands, I can’t say exactly how the system will behave, but there are a [...]]]></description>
			<content:encoded><![CDATA[<p>With the impending release of <a href="http://www.apple.com/ipad/">the iPad 2</a>, understanding how to program multithreaded applications will quickly become paramount as applications continue to push the envelope to make immersive experiences with high-performance computation. Now, without actually <em>having</em> a multicore iPad in my hands, I can’t say exactly how the system will behave, but there are a few best practices we should all be aware of when writing iOS code:</p>
<ul>
<li><strong>Using <a href="http://developer.apple.com/library/mac/#referencelibrary/GettingStarted/GettingStartedWithCoreData/">Core Data</a>?</strong> You can’t share access to an <a href="http://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/"><code>NSManagedObjectContext</code></a> across multiple threads, <a href="http://developer.apple.com/library/mac/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html">dispatch queues</a>, or <a href="http://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperationQueue_class/"><code>NSOperation</code> queues</a>, so for each one you’ll need to create a new instance. Similarly, don’t pass an <a href="http://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObject_Class/"><code>NSManagedObject</code></a> or subclass thereof between threads. Give each of your objects a unique ID—<a href="http://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFUUIDRef/Reference/reference.html"><code>CFUUID</code></a> works well for this—and pass the ID around, pulling a new object out of your <code>NSManagedObjectContext</code> for each thread. It’s a pain, but that’s how to (safely) get around threading and Core Data.</li>
<li><strong><em>Always</em> call UIKit updates from the main thread.</strong> Whatever you’re doing to your user interface, be it updating a label, loading an image into an image view, <em>anything</em> that’ll be rendered to screen—and some things that won’t—should be run on the main thread. There are two main ways to do this:
<ol>
<li><em>Use Grand Central Dispatch.</em> Using <a href="http://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dispatch_get_main_queue.3.html"><code>dispatch_get_main_queue()</code></a>, you can get a reference to the main queue and submit blocks to it for updating your UI. This is typically a clean, easy way to refactor existing code for thread-aware programming.</li>
<li><em>Use <a href="http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelectorOnMainThread:withObject:waitUntilDone:"><code>-performSelectorOnMainThread:withObject:waitUntilDone:</code></a> and friends.</em> This has the drawback of only working for methods that take one or zero Objective-C objects as arguments, but can be a quick and easy way to use fire-and-forget methods like <a href="http://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html#//apple_ref/occ/instm/UITableView/reloadData"><code>-reloadData</code></a> on <a href="http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html"><code>UITableView</code></a>.</li>
</ol>
</li>
<li><strong>Think about how you declare your properties.</strong> How many people have been using atomic properties? Before now, not many. In fact, before now, it was typically useless, as the chances of something interrupting your accessor methods was pretty low. Now, though, if you’re planning on accessing an object from multiple threads, you <em>really</em> need to control access to your properties.</li>
<li><strong>Use locks.</strong> Locks, long the scourge of the multithreaded-code author, are simply essential for some parts of multithreaded programming. Whether you’re using <a href="http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSLock_Class/Reference/Reference.html"><code>NSLock</code></a> or a lower-level lock, or even something like Grand Central Dispatch’s counting semaphore type, <a href="http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/doc/uid/TP40008079-CH2-SW37"><code>dispatch_semaphore_t</code></a>, protect critical regions of your code from multiple accessors with (carefully-thought-out) locked access.</li>
</ul>
<p>This list is by no means exhaustive, and Apple can do a lot to make this irrelevant (such as make UIKit threadsafe, which would be a <em>killer</em> iOS 5.0 feature), but with the iPad 2’s arrival, developers can no longer assume safety from threading problems. Be sure also to read Apple’s <a href="http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/">Threading Programming Guide</a> to get anything I’ve left out.</p>
<p>It also makes a great excuse to buy an iPad 2. I mean, you need to <em>test</em> this, right?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2011/03/03/ios-programming-for-multicore-processors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Programming: Hard Mode</title>
		<link>http://blog.slaunchaman.com/2011/02/05/iphone-programming-hard-mode/</link>
		<comments>http://blog.slaunchaman.com/2011/02/05/iphone-programming-hard-mode/#comments</comments>
		<pubDate>Sat, 05 Feb 2011 16:14:19 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Objective-C Runtime]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=375</guid>
		<description><![CDATA[After a conversation with some co-workers, I discussed how it would be technically possible to write an iPhone app using only a main.m file—no separate class files. This post is the result of that. It’s definitely doable, but not something I’d ever recommend for shipping code. The code is explained below, but you can get [...]]]></description>
			<content:encoded><![CDATA[<p>After a conversation with some co-workers, I discussed how it would be technically possible to write an iPhone app using only a <tt>main.m</tt> file—no separate class files. This post is the result of that. It’s definitely doable, but not something I’d ever recommend for shipping code.<br />
The code is explained below, but you can get the full source in <a href="https://github.com/SlaunchaMan/iPhoneHardMode">my public GitHub repository</a>.</p>
<h2>Getting Started</h2>
<p>By default, an iPhone application template gives you a <tt>main.m</tt> file, but it’s pretty basic:</p>
<pre class="brush: objc; first-line: 9; title: ; notranslate">#import &lt;UIKit/UIKit.h&gt;

int main(int argc, char *argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}</pre>
<p>To go from that code to running your application, a few things happen, mostly in <code>UIApplicationMain</code>. Its last argument, typically <code>nil</code>, is a pointer to an <code>NSString</code> that specifies the class name of the application delegate. Normally, your <tt>Info.plist</tt> file specifies a nib file (the keys <code>NSMainNibFile</code> or <code>NSMainNibFile~ipad</code>), which in turn specifies the application delegate, instantiates it, etc.</p>
<p>So, first, delete the <tt>MainWindow.xib</tt> file, then all other class files (<tt>MyCoolAppDelegate.h</tt> and <tt>MyCoolAppDelegate.m</tt>, for instance). There should be three files left in the iPhone application: your <tt>Prefix.pch</tt> file (which we could technically do without), <tt>main.m</tt>, and your <tt>Info.plist</tt> file.</p>
<h2>The Fun Begins</h2>
<h3>Administrivia: Creating Strings</h3>
<p>Since, as a part of the exercise, we don’t want to use Objective-C, I also decided against using any constant <code>NSString</code>s (<code>@"Hello, World!"</code> and the like). To create a string, then, we’ll use <code>CFString</code>s. I created a macro to create one from a C string using ASCII encoding:</p>
<pre class="brush: objc; first-line: 16; title: ; notranslate">#define JK_EasyCFString(X)
(CFStringCreateWithCString(kCFAllocatorDefault, (X), kCFStringEncodingASCII))</pre>
<p>Don’t forget to call <code>CFRelease()</code> when you’re done with it, though.</p>
<h3>Creating a Class</h3>
<p>We need to modify the call to <code>UIApplicationMain</code> to include our application delegate class if we want this app to be anything more than a blank screen. What class name can we give it, though? We’ll need to create a class, and we’ll call it “<code>HardModeAppDelegate</code>.”</p>
<pre class="brush: objc; first-line: 41; highlight: [42]; title: ; notranslate">	// Create a class to serve as our application delegate.
	Class appDelegate = objc_allocateClassPair(NSClassFromString((id)NSObjectString), &quot;HardModeAppDelegate&quot;, 0);</pre>
<p>The first argument is a toll-free bridged <code>CFString</code> that specifies <code>NSObject</code> as the superclass, then we pass in the name of the class as a C string and 0 for the number of extra bytes we want (which is nearly always zero). Now let’s set it up a bit:</p>
<pre class="brush: objc; first-line: 44; highlight: [46,49,50,51,52,65]; title: ; notranslate">	// Conform to the UIApplciationDelegate protocol.
	Protocol *appDelegateProto = NSProtocolFromString((id)UIApplicationDelegateString);
	class_addProtocol(appDelegate, appDelegateProto);

	// Add methods.
	SEL applicationDidFinishLaunchingWithOptions = NSSelectorFromString((id)appDidFinishLaunchingOptionsString);
	class_addMethod(appDelegate,
					applicationDidFinishLaunchingWithOptions,
					(IMP)UIApplicationDelegate_ApplicationDidFinishLaunchingWithOptions,
					&quot;v@:@@&quot;);

	SEL dealloc = NSSelectorFromString((id)deallocString);
	class_addMethod(appDelegate,
					dealloc,
					(IMP)appDelegate_dealloc,
					&quot;v@:&quot;);

	// Add an instance variable for the window.
	class_addIvar(appDelegate,
				  &quot;window&quot;,
				  sizeof(id),
				  log2(sizeof(id)),
				  &quot;@&quot;);

	// Now that we’ve added ivars, we can register the class.
	objc_registerClassPair(appDelegate);</pre>
<p>That code is the same as writing an <code>@interface</code> block for a new class, setting up ivars, conforming to protocols, and defining instance methods, but done using the runtime calls instead. Methods are actually C functions, but with two arguments prepended to the argument list: <code>id self</code> and <code>SEL _cmd</code>. Those arguments are actually passed to <em>every</em> Objective-C method, but usually hidden.</p>
<h3>Custom Message Sending</h3>
<p>The rest of the application is more of this bootstrapped Objective-C in C, but there are a few wrinkles worth discussing, most notably the use of <code>objc_msgSend</code> with methods that return other than <code>id</code> and/or have additional arguments beyond <code>self</code> and <code>_cmd</code>. For instance, to call <code>-bounds</code> on a <code>UIScreen</code> object, I had to cast the return type of <code>objc_msgSend</code> to <code>CGRect</code>:</p>
<pre class="brush: objc; first-line: 134; highlight: [135]; title: ; notranslate">CGRect (*msgSendBounds)(id self, SEL _cmd);
  msgSendBounds = (CGRect(*)(id, SEL))objc_msgSend_stret;</pre>
<p>Similarly, when calling <code>-initWithFrame:</code> on a <code>UIWindow</code> or <code>UILabel</code>, I casted it to take in a <code>CGRect</code> argument:</p>
<pre class="brush: objc; first-line: 141; highlight: [142]; title: ; notranslate">id (*msgSendCGRect)(id self, SEL _cmd, CGRect rect);
msgSendCGRect = (id(*)(id, SEL, CGRect))objc_msgSend;</pre>
<h3>Accessing Instance Variables</h3>
<p>In my implementation of the <code>HardModeAppDelegate</code> class’s <code>-dealloc</code> method, I need to access the <code>window</code> instance variable to send it a <code>-release</code> message. Using the <code>Ivar</code> type and the <code>object_getIvar</code> function, it becomes easy:</p>
<pre class="brush: objc; first-line: 196; title: ; notranslate">Ivar windowIvar = class_getInstanceVariable(self-&gt;isa, &quot;window&quot;);
id window = object_getIvar(self, windowIvar);</pre>
<h2>So what do we have?</h2>
<p>To be clear, this is <em>not</em> writing an iPhone app without using Objective-C, per se. The runtime is still being used, messages are being sent, all that. But it <em>is</em> an illustration of some of the heavy lifting that the runtime does for you. I would caution against adopting this practice for real, shipping apps.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2011/02/05/iphone-programming-hard-mode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Take Me Home</title>
		<link>http://blog.slaunchaman.com/2010/12/18/take-me-home/</link>
		<comments>http://blog.slaunchaman.com/2010/12/18/take-me-home/#comments</comments>
		<pubDate>Sat, 18 Dec 2010 05:09:55 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[My Software]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[news]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Take Me Home]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=349</guid>
		<description><![CDATA[Take Me Home was a good “Hello, World!” iOS app, but its time has come. I’ve pulled Take Me Home from the App Store. Goodnight, sweet prince.]]></description>
			<content:encoded><![CDATA[<p>Take Me Home was a good “Hello, World!” iOS app, but its time has come. I’ve pulled Take Me Home from the App Store. Goodnight, sweet prince.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/12/18/take-me-home/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Autorelease is Not Your Friend</title>
		<link>http://blog.slaunchaman.com/2010/11/16/autorelease-is-not-your-friend/</link>
		<comments>http://blog.slaunchaman.com/2010/11/16/autorelease-is-not-your-friend/#comments</comments>
		<pubDate>Tue, 16 Nov 2010 05:00:15 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[autorelease]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[NSAutoreleasePool]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=334</guid>
		<description><![CDATA[How many times have you written this line? NSMutableArray *foo = [[[NSMutableArray alloc] init] autorelease]; At first glance, it looks fine. foo is an autoreleased NSMutableArray that you can use and, at the end of the method, it’s gone into the ether of the autorelease pool. Don’t get me wrong, most of the time, this [...]]]></description>
			<content:encoded><![CDATA[<p>How many times have you written this line?</p>
<blockquote><p><code>NSMutableArray *foo = [[[NSMutableArray alloc] init] autorelease];</code></p></blockquote>
<p>At first glance, it looks fine. <code>foo</code> is an autoreleased <code>NSMutableArray</code> that you can use and, at the end of the method, it’s gone into the ether of the autorelease pool. Don’t get me wrong, <em>most of the time</em>, this use of <code>-autorelease</code> is acceptable. But, in this post, I’ll try to convince you to use autorelease differently in subtle ways.<span id="more-334"></span></p>
<h3>Avoid Enormous Pools</h3>
<p>Back to the first line of code. Let’s look at a real-world example of using <code>-autorelease</code> this way:</p>
<blockquote><p><code>
<pre>- (void)doSomeStuffWithAHugeArray:(NSArray *)array
{
    for (NSUInteger i = 0; i &lt; [array count]; i++) {
        NSDictionary *aDict = (NSDictionary *)[array objectAtIndex:i];

        NSMutableArray *foo = [[[NSMutableArray alloc] init] autorelease];
        [foo addObject:[aDict objectForKey:@"someKey"]];

        // Some general processing of foo here.
    }
}</pre>
<p></code></p></blockquote>
<p>To the programmer, this appears perfectly valid. <code>foo</code> will be created once for each object in <code>array</code> and some processing will occur on it. You don’t need to worry about memory management since it’s autoreleased, right?</p>
<p>Right?</p>
<p>But what happens if there are 4 million items in this array? And you’re running on an iPhone? See, the problem with autorelease pools is that they drain their contents at some future point in the run loop. During your methods’ stack frame, the app never returns to the run loop. These objects keep getting added to the autorelease pool, and until the method is done, they don’t go anywhere. On the Mac this isn’t as much of an issue, since unused objects will get paged out of active memory, but on iOS, your app will be terminated when you run out of memory.</p>
<p>What to do? There are two approaches: first, implement a counter:</p>
<blockquote><p><code>
<pre>NSAutoreleasePool *pool = nil;
NSUInteger count = 0;

for (NSUInteger i = 0; i &lt; [array count]; i++) {
    if (pool == nil) {
        pool = [[NSAutoreleasePool alloc] init];
    }

    static NSUInteger count = 0;
    NSDictionary *aDict = (NSDictionary *)[array objectAtIndex:i];

    NSMutableArray *foo = [[[NSMutableArray alloc] init] autorelease];
    [foo addObject:[aDict objectForKey:@"someKey"]];

    // Some general processing of foo here.

    count++;
    if (count % 1000 == 0) {
        // count is a multiple of 1,000
        [pool drain];
        pool = nil;
    }
}
[pool drain];</pre>
<p></code></p></blockquote>
<p>What have we gained, aside from a lot more code? Every 1,000 iterations through this loop, the autorelease pool that we’ve created drains its contents; this eliminates the possibility of millions of <code>NSMutableArray</code>s littering the contents of memory. In this case it’s unnecessary as we could just release <code>foo</code> at the end of the loop, but in most cases you’ll be dealing with other methods, either your own or those provided by Cocoa Touch or some library, that return autoreleased objects. This method prevents those objects from gumming up the works too much. As an example, if you’re processing JSON—let’s say Reddit comments—you can easily get millions of autoreleased <code>NSString</code> objects created, and significant processing of them can become unwieldy.</p>
<h3>Treat <code>-autorelease</code> like <code>-release</code></h3>
<p>Here’s another typical pattern you see in Objective-C code:</p>
<blockquote><p><code>
<pre>MyAwesomeObject *bar = [[[MyAwesomeObject alloc] init] autorelease];
[NSThread detachNewThreadSelector:@selector(extraLongComputation:)
                         toTarget:self
                       withObject:bar];
bar.someProperty = 42;</pre>
<p></code></p></blockquote>
<p>That looks OK at first, but depending on how your app is running, you could be adding <code>bar</code> to an autorelease pool that is drained while <code>-extraLongComputation</code> is running. If you’re performing selectors after a delay or using an <code>NSTimer</code>, this is especially likely. In this case, I like to treat <code>-autorelease</code> like <code>-release</code>:</p>
<blockquote><p><code>
<pre>MyAwesomeObject *bar = [[MyAwesomeObject alloc] init];
[NSThread detachNewThreadSelector:@selector(extraLongComputation:)
                         toTarget:self
                       withObject:bar];
bar.someProperty = 42;
[bar autorelease];</pre>
<p></code></p></blockquote>
<p>By itself, this isn’t sufficient. However, when coupled with this code:</p>
<blockquote><p><code>
<pre>- (void)extraLongComputation:(MyAwesomeObject *)obj
{
    [obj retain];

    // TODO: write computation code.

    [obj release];
}</pre>
<p></code></p></blockquote>
<p>This ensures that <code>bar</code> survives long enough for your computation.</p>
<p>Nothing I’ve written here is a panacea, and I’m sure it’s all been written before (and probably better), but my hope is to at least encourage you to think more about the memory management of your application, lest you find yourself debugging odd crashes the night before a deadline.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/11/16/autorelease-is-not-your-friend/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Xcode 3.2: Using GDB as a Non-Admin User</title>
		<link>http://blog.slaunchaman.com/2010/07/20/xcode-3-2-using-gdb-as-a-non-admin-user/</link>
		<comments>http://blog.slaunchaman.com/2010/07/20/xcode-3-2-using-gdb-as-a-non-admin-user/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 18:30:35 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[Systems Administration]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[command-line]]></category>
		<category><![CDATA[dscl]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=310</guid>
		<description><![CDATA[New in Xcode 3.2 is an authorization setting that looks like this: &#60;dict&#62; &#60;key&#62;allow-root&#60;/key&#62; &#60;false/&#62; &#60;key&#62;class&#60;/key&#62; &#60;string&#62;rule&#60;/string&#62; &#60;key&#62;comment&#60;/key&#62; &#60;string&#62;For use by Apple. WARNING: administrators are advised not to modify this right.&#60;/string&#62; &#60;key&#62;k-of-n&#60;/key&#62; &#60;integer&#62;1&#60;/integer&#62; &#60;key&#62;rule&#60;/key&#62; &#60;array&#62; &#60;string&#62;is-admin&#60;/string&#62; &#60;string&#62;is-developer&#60;/string&#62; &#60;string&#62;authenticate-developer&#60;/string&#62; &#60;/array&#62; &#60;key&#62;shared&#60;/key&#62; &#60;true/&#62; &#60;/dict&#62; The upshot of this is that if you aren’t in the _developer group [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://developer.apple.com/iphone/library/releasenotes/DeveloperTools/RN-Xcode/#//apple_ref/doc/uid/TP40001051-DontLinkElementID_13">New in Xcode 3.2</a> is an authorization setting that looks like this:</p>
<blockquote><pre>&lt;dict&gt;
	&lt;key&gt;allow-root&lt;/key&gt;
	&lt;false/&gt;
	&lt;key&gt;class&lt;/key&gt;
	&lt;string&gt;rule&lt;/string&gt;
	&lt;key&gt;comment&lt;/key&gt;
	&lt;string&gt;For use by Apple.  WARNING: administrators are advised not to
	        modify this right.&lt;/string&gt;
	&lt;key&gt;k-of-n&lt;/key&gt;
	&lt;integer&gt;1&lt;/integer&gt;
	&lt;key&gt;rule&lt;/key&gt;
	&lt;array&gt;
		&lt;string&gt;is-admin&lt;/string&gt;
		&lt;string&gt;is-developer&lt;/string&gt;
		&lt;string&gt;authenticate-developer&lt;/string&gt;
	&lt;/array&gt;
	&lt;key&gt;shared&lt;/key&gt;
	&lt;true/&gt;
&lt;/dict&gt;</pre>
</blockquote>
<p>The upshot of this is that if you aren’t in the <code>_developer</code> group in the local directory, you’ll have to authenticate as an administrator to use <code>gdb</code> or some of the performance tools. For the vast majority of developers on Mac OS X, who run as an administrator, this is fine, but if you’re running as a regular user, either for security reasons or because you’re in something like a lab setting, this can be a problem. To add a user to the <code>_developer</code> group, use the <code>dscl</code> command:</p>
<blockquote><p><code>dscl . -append /Groups/_developer GroupMembership <strong>UserName</strong></code></p></blockquote>
<p>Replace <code><strong>UserName</strong></code> with the short name of your user account (or <code>$(whoami)</code>) and you should be all set.</p>
<p>If you’re administering Mac OS X in a lab setting, you can either create a LaunchAgent that handles this or a login hook. See the Apple tech note <a href="http://developer.apple.com/mac/library/technotes/tn2008/tn2228.html">“Running At Login”</a> for more information on login hooks. As an added touch, my login and logout scripts to handle this also remove all users from the group, like so:</p>
<blockquote><p><code>dscl . -delete /Groups/_developer GroupMembership</code></p></blockquote>
<p>If the <code>GroupMembership</code> key doesn’t exist, <code>dscl</code> will create it—and it doesn’t exist by default—so deleting it outright shouldn’t cause any problems.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/07/20/xcode-3-2-using-gdb-as-a-non-admin-user/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Dealing with Special Characters in iPhone 4 Graphics Filenames with Subversion</title>
		<link>http://blog.slaunchaman.com/2010/07/10/dealing-with-special-characters-in-iphone-4-graphics-filenames-with-subversion/</link>
		<comments>http://blog.slaunchaman.com/2010/07/10/dealing-with-special-characters-in-iphone-4-graphics-filenames-with-subversion/#comments</comments>
		<pubDate>Sun, 11 Jul 2010 01:48:27 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[command-line]]></category>
		<category><![CDATA[convenience]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPhone 4]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=304</guid>
		<description><![CDATA[With the iPhone 4’s high-resolution screen, designers need to create two sets of art; the guidelines are to name the files like so: SomeCoolImage.png and SomeCoolImage@2x.png. Unfortunately, if you try to add these files to an SVN repository, the @ symbol throws them off: $ svn add Icon\@2x~iphone.png svn: warning: 'Icon' not found The fix, [...]]]></description>
			<content:encoded><![CDATA[<p>With the iPhone 4’s high-resolution screen, designers need to create two sets of art; the guidelines are to name the files like so: <code>SomeCoolImage.png</code> and <code>SomeCoolImage@2x.png</code>. Unfortunately, if you try to add these files to an SVN repository, the <code>@</code> symbol throws them off:</p>
<blockquote><pre>$ svn add Icon\@2x~iphone.png
svn: warning: 'Icon' not found</pre>
</blockquote>
<p>The fix, thanks to the <a href="http://groups.google.com/group/subversion_users/browse_thread/thread/2b8e8e05e04fa240/">subversion_users Google Group</a>, is to add another <code>@</code> to the end of the filename, like so:</p>
<blockquote><pre>$ svn add ./Icon\@2x~iphone.png@
A  (bin)  Icon@2x~iphone.png</pre>
</blockquote>
<p>If you’d like to do this for all of your high-resolution art in a folder, here’s a tiny Bash command for the task:</p>
<blockquote><pre>for x in `ls *\@*`; do svn add $x\@; done</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/07/10/dealing-with-special-characters-in-iphone-4-graphics-filenames-with-subversion/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Take Me Home Now Free</title>
		<link>http://blog.slaunchaman.com/2010/05/10/take-me-home-now-free/</link>
		<comments>http://blog.slaunchaman.com/2010/05/10/take-me-home-now-free/#comments</comments>
		<pubDate>Tue, 11 May 2010 04:12:41 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[My Software]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[shameless plug]]></category>
		<category><![CDATA[Take Me Home]]></category>
		<category><![CDATA[updates]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=267</guid>
		<description><![CDATA[Take Me Home is an ancient, buggy iPhone app that was my &#8220;Hello, World!&#8221; in the App Store. Its sale rate has plummeted to only a couple of buyers a week and, with the prevalence of real, honest-to-God GPS apps in the store these days, its usefulness is questionable. So from here on out, it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.slaunchaman.com/my-software/take-me-home/">Take Me Home</a> is an ancient, buggy iPhone app that was my &ldquo;Hello, World!&rdquo; in the App Store. Its sale rate has plummeted to only a couple of buyers a week and, with the prevalence of real, honest-to-God GPS apps in the store these days, its usefulness is questionable. So from here on out, it&#8217;s free. I can&#8217;t promise to continue supporting it&mdash;especially for new devices and APIs&mdash;so the best I can do may be to remove it from the store in the event that some update breaks it.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/05/10/take-me-home-now-free/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

