<?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>Thu, 19 Aug 2010 21:14:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<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[Mac Systems Administration]]></category>
		<category><![CDATA[Programming Tips]]></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[Systems Administration]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=310</guid>
		<description><![CDATA[New in Xcode 3.2 is]]></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>0</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]]></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>2</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]]></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>
		<item>
		<title>Quick Tip: Don&#8217;t Do This</title>
		<link>http://blog.slaunchaman.com/2010/05/10/quick-tip-dont-do-this/</link>
		<comments>http://blog.slaunchaman.com/2010/05/10/quick-tip-dont-do-this/#comments</comments>
		<pubDate>Tue, 11 May 2010 04:01:44 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[gotchas]]></category>
		<category><![CDATA[NSObject]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Objective-C Runtime]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=263</guid>
		<description><![CDATA[I could not find out]]></description>
			<content:encoded><![CDATA[<p>I could <em>not</em> find out where a bug was coming from for the life of me today. Naturally it one of those &ldquo;assignment instead of equality&rdquo; bugs that seem to crop up when trying to code too quickly. The difference here was that I had implemented a subclass of <code>NSObject</code> that reimplemented the method <a href="http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/doc/uid/20000050-SW5"><code>+resolveInstanceMethod:</code></a>. So, the code went like this:<code>
<pre>+ ( BOOL )resolveInstanceMethod:( SEL )sel
{
    if ( sel = @selector( setFoobar: )) {
        return class_addMethod([ self class ], sel, ( IMP )setFB, "v@:@" );
    } else if ( sel = @selector( foobar )) {
        return class_addMethod([ self class ], sel, ( IMP )getFB, "@@:" );
    } else {
        return [ super resolveInstanceMethod:sel ];
    }
}</pre>
<p></code><br />
For those of you keeping score at home, when the Objective-C runtime tried to resolve <em>any</em> selector, this method happily added a selector for <code>-setFoobar:</code> to <code>self</code>&rsquo;s class and returned <code>YES</code>.</p>
<p>Don&rsquo;t do this.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/05/10/quick-tip-dont-do-this/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New iPhone Project: uWarranty</title>
		<link>http://blog.slaunchaman.com/2010/03/09/new-iphone-project-uwarranty/</link>
		<comments>http://blog.slaunchaman.com/2010/03/09/new-iphone-project-uwarranty/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 17:56:59 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[My Software]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[news]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[uWarranty]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=244</guid>
		<description><![CDATA[So, I created a new]]></description>
			<content:encoded><![CDATA[<p>So, I created a new iPhone application called uWarranty. It used an unpublished Apple API for warranty status (from selfsolve.apple.com), and so I got this after submitting it:</p>
<blockquote><p>Thank you for submitting your application to the App Store. Unfortunately, your application, uWarranty, cannot be added to the App Store because it violates section 3.3.7 of the iPhone Developer Program License Agreement:</p>
<p>&#8220;Applications may not perform any functions or link to any content or use any robot, spider, site search or other retrieval application or device to scrape, retrieve or index services provided by Apple or its licensors, or to collect, disseminate or use information about users for any unauthorized purpose.&#8221;</p></blockquote>
<p>OK, I get it. That&rsquo;s fine and is Apple&rsquo;s prerogative. But now I have this program and all the development time that went into it. So what do I do? I guess the answer is to open-source it, just like <a title="AppSales Mobile" href="http://github.com/omz/AppSales-Mobile" target="_blank">AppSales Mobile</a>. Watch this space for more details as I clean up the code and throw it up on a public repository somewhere.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/03/09/new-iphone-project-uwarranty/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cocoa Touch Tutorial: Stripping Non-Alphanumeric Characters on Entry in a UITextField</title>
		<link>http://blog.slaunchaman.com/2010/02/26/cocoa-touch-tutorial-stripping-non-alphanumeric-characters-on-entry-in-a-uitextfield/</link>
		<comments>http://blog.slaunchaman.com/2010/02/26/cocoa-touch-tutorial-stripping-non-alphanumeric-characters-on-entry-in-a-uitextfield/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 06:14:15 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[NSCharacterSet]]></category>
		<category><![CDATA[NSMutableString]]></category>
		<category><![CDATA[NSString]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tutorials]]></category>
		<category><![CDATA[UITextField]]></category>
		<category><![CDATA[UITextFieldDelegate]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=216</guid>
		<description><![CDATA[In a previous post, I]]></description>
			<content:encoded><![CDATA[<p>In a <a href="http://blog.slaunchaman.com/2009/11/01/cocoa-tutorial-strip-non-alphanumeric-characters-from-an-nsstring/">previous post</a>, I showed you how to trim non-alphanumeric characters from a string. Here I&rsquo;ll go more in-depth and show a method that I wrote to restrict text entry in a <a href="http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UITextField_Class/Reference/UITextField.html"><code>UITextField</code></a> to alphanumeric characters. Since I also wanted the characters to be uppercase, I&rsquo;ll also ensure that only uppercase characters are allowed.</p>
<p>This should all happen in the <em><code>-&nbsp;(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string</code></em> method of your <code>UITextField</code>&rsquo;s delegate (which, of course, must implement the <a href="http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UITextFieldDelegate_Protocol/UITextFieldDelegate/UITextFieldDelegate.html"><code>UITextFieldDelegate</code> protocol</a>). I&rsquo;ve implemented it as follows:</p>
<blockquote><pre>- ( BOOL )textField:( UITextField * )textField
shouldChangeCharactersInRange:( NSRange )range
  replacementString:( NSString * )string
{
    /*
     * We only want uppercase letters and numbers in this text field, so if
     * this method is adding something else, we don't want it. But we also
     * want to support copy-and-paste, so it's not always going to be one
     * character added.
     */
    BOOL shouldAllowChange = YES;</pre>
</blockquote>
<p>The <em><code>shouldAllowChange</code></em> variable is set to <code>YES</code> initially because we <em>want</em> to allow this change when possible. The method will test the string to see if it meets criteria for rejection as we move forward.</p>
<blockquote><pre>    NSMutableString *newReplacement =
    [[ NSMutableString alloc ] initWithString:[ string uppercaseString ]];

    if ( ! [ string isEqualToString:newReplacement ]) {
        shouldAllowChange = NO;
    }</pre>
</blockquote>
<p>First, we define <em><code>newReplacement</code></em>. It&rsquo;s an <a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSMutableString_Class/Reference/Reference.html"><code>NSMutableString</code></a> so that if we discover non-alphanumeric characters in it, we can remove them on-the-fly. It also serves as a convenient string against which we can test to see if <code>string</code> is already uppercase.</p>
<blockquote><pre>    NSCharacterSet *desiredCharacters =
    [ NSCharacterSet alphanumericCharacterSet ];

    for ( NSUInteger i = 0; i < [ newReplacement length ]; i++ ) {
        unichar currentCharacter = [ newReplacement characterAtIndex:i ];

        if ( ! [ desiredCharacters characterIsMember:currentCharacter ]) {
            shouldAllowChange = NO;
            [ newReplacement deleteCharactersInRange:NSMakeRange( i, 1 )];
            i--;
        }
    }</pre>
</blockquote>
<p>In this section, we define the <a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSCharacterSet_Class/Reference/Reference.html"><code>NSCharacterSet</code></a> that we want to work with - in this case, the alphanumeric character set. We go through one character by a time and if the current character isn&rsquo;t alphanumeric, we remove it from the <code>NSMutableString</code> (decrementing <em><code>i</code></em> so that we don&rsquo;t inadvertently skip a character) and set our <code>shouldAllowChange</code> flag accordingly.</p>
<blockquote><pre>    if ( shouldAllowChange ) {
        [ newReplacement release ];
        return YES;
    } else {
        [ textField setText:[[ textField text ]
                             stringByReplacingCharactersInRange:range
                             withString:newReplacement ]];
        [ newReplacement release ];
        return NO;
    }
}</pre>
</blockquote>
<p>To finish, if <code>shouldAllowChange</code> is still true, we return <code>YES</code> and allow the replacement characters to be added. Otherwise, we return <code>NO</code>, but not before using our replacement replacement string (say that ten times fast) to manually edit the text field&rsquo;s text. The end result is a text field that will consist only of uppercase letters and numbers.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/02/26/cocoa-touch-tutorial-stripping-non-alphanumeric-characters-on-entry-in-a-uitextfield/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cocoa Tutorial: Strip Non-Alphanumeric Characters from an NSString</title>
		<link>http://blog.slaunchaman.com/2009/11/01/cocoa-tutorial-strip-non-alphanumeric-characters-from-an-nsstring/</link>
		<comments>http://blog.slaunchaman.com/2009/11/01/cocoa-tutorial-strip-non-alphanumeric-characters-from-an-nsstring/#comments</comments>
		<pubDate>Sun, 01 Nov 2009 16:36:46 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[convenience]]></category>
		<category><![CDATA[NSCharacterSet]]></category>
		<category><![CDATA[NSString]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=192</guid>
		<description><![CDATA[Let’s say you have an]]></description>
			<content:encoded><![CDATA[<p>Let’s say you have an NSString that contains both alphanumeric and non-alphanumeric characters and you want to strip the non-alphanumeric characters out of it. The hard way is to manually go through, character-by-character, and put the character in a new string if it matches certain criteria. But why do it the hard way?</p>
<p>Apple provides a class that we can use for this to great effect: <a title="NSCharacterSet Class Reference" href="http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSCharacterSet_Class/Reference/Reference.html"><code>NSCharacterSet</code></a>. We want alphanumeric characters, so we can create a character set of the characters we want using this method:</p>
<blockquote><p><code>NSCharacterSet *alphanumericSet = [ NSCharacterSet alphanumericCharacterSet ];</code></p></blockquote>
<p>Now we have a character set like we want. We just need a way to turn our string into a string that contains only those characters. Unfortunately, the closest thing in <code>NSString</code>’s implementation is the <code>-stringByTrimmingCharactersInSet:</code> method. But that seems to do the <em>opposite</em> of what we want. Fortunately <code>NSCharacterSet</code> has our back here. We can use the <code>-invertedSet</code> method. So here is our final code:</p>
<blockquote><p><code>NSString *beginningString = @"Some string with non-alphanumeric characters. !@#$%^&amp;*()";<br />
NSCharacterSet *nonalphanumericSet = [[ NSCharacterSet alphanumericCharacterSet ] invertedSet ];<br />
NSString *endingString = [ beginningString stringByTrimmingCharactersInSet:nonalphanumericSet ];</code></p></blockquote>
<p>In this example, <code>endingString</code> will be equal to “Somestringwithnonalphanumericcharacters”.</p>
<p><strong>UPDATE:</strong> As it turns out, this only works if the non-alphanumeric characters are at the beginning or end of the <code>NSString</code>. Whoops.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2009/11/01/cocoa-tutorial-strip-non-alphanumeric-characters-from-an-nsstring/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cocoa Touch Tutorial: Extract Address Book Address Values on iPhone OS</title>
		<link>http://blog.slaunchaman.com/2009/01/21/cocoa-touch-tutorial-extract-address-book-address-values-on-iphone-os/</link>
		<comments>http://blog.slaunchaman.com/2009/01/21/cocoa-touch-tutorial-extract-address-book-address-values-on-iphone-os/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 21:07:52 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[Address Book]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=164</guid>
		<description><![CDATA[This is the first of]]></description>
			<content:encoded><![CDATA[<p>This is the first of what I hope to be several Cocoa Touch tutorials on this site.  I was doing some furious Googling last night trying to find out how to get a contact’s street address from the Address Book for an upcoming update to <a title="Take Me Home" href="http://blog.slaunchaman.com/take-me-home">Take Me Home</a>, and I realized that it’s complicated and there aren’t any good tutorials online.  So, after I figured it out, I commented it up so that hopefully, if you’re reading this, you’ll save some time that I didn’t.</p>
<p>Before you read this tutorial, you should go through Apple’s excellent <a title="Address Book Programming Guide for iPhone OS" href="http://developer.apple.com/iphone/library/documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/">Address Book Programming Guide for iPhone OS</a>.  This tutorial will rely on the QuickStart application you write in the guide, so do that first.<br />
The first thing we need to do is add an address field to the QuickStart application.  Use Interface Builder to add a new UILabel underneath the two you already have.  You may want to stretch it to fill the entire width of the screen, like so:</p>
<div id="attachment_165" class="wp-caption aligncenter" style="width: 410px"><img class="size-full wp-image-165" title="Address Label" src="http://blog.slaunchaman.com/wp-content/uploads/2009/01/picture-1.png" alt="Add a new UILabel underneath the exisiting two." width="400" height="582" /><p class="wp-caption-text">Add a new UILabel underneath the exisiting two.</p></div>
<p>Now, add the information about this label to <strong>QuickStartViewController.h</strong>:</p>
<blockquote><p><code> </code></p>
<pre>//
//  QuickStartViewController.h
//  QuickStart
//

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

@interface QuickStartViewController : UIViewController &lt;ABPeoplePickerNavigationControllerDelegate&gt; {
    IBOutlet UILabel *firstName;
    IBOutlet UILabel *lastName;
    <strong>IBOutlet UILabel *addressLabel;</strong>
}

@property (nonatomic, retain) UILabel *firstName;
@property (nonatomic, retain) UILabel *lastName;
<strong>@property (nonatomic, retain) UILabel *addressLabel;</strong>

- (IBAction)showPicker:(id)sender;

@end</pre>
</blockquote>
<p>Be sure to go back into Interface Builder and connect File’s Owner in <strong>QuickStartViewController.xib</strong> to addressLabel.</p>
<p>Now, we have to change the method that gets called when you click on a person in the <em>ABPeoplePicker</em>.  As it is at the end of the QuickStart tutorial, once you select a person the picker is dismissed.  So, we do the following in <strong>QuickStartViewController.m</strong>:</p>
<blockquote><p><code> </code></p>
<pre>- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person {
    NSString *name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
    self.firstName.text = name;
    [name release];

    name = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
    self.lastName.text = name;
    [name release];

    <del>[self dissmissModalViewControllerAnimated:YES];</del>

<strong>    return YES;</strong>
}</pre>
</blockquote>
<p>Note that you have to delete the line that dismisses the modal view controller; if you don’t, the people picker is dismissed before you have a chance to get the address.  When you delete it, the people picker will continue when you select a person.  Next up, we have to write the method for when someone selects an address on the next screen.  Here’s the method:</p>
<blockquote><p><code> </code></p>
<pre>- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person
                                property:(ABPropertyID)property
                              identifier:(ABMultiValueIdentifier)identifier {
    <strong>// Only inspect the value if it's an address.
    if (property == kABPersonAddressProperty) {
        /*
         * Set up an ABMultiValue to hold the address values; copy from address
         * book record.
         */
        ABMultiValueRef multi = ABRecordCopyValue(person, property);

        // Set up an NSArray and copy the values in.
        NSArray *theArray = [(id)ABMultiValueCopyArrayOfAllValues(multi) autorelease];

        // Figure out which values we want and store the index.
        const NSUInteger theIndex = ABMultiValueGetIndexForIdentifier(multi, identifier);

        // Set up an NSDictionary to hold the contents of the array.
        NSDictionary *theDict = [theArray objectAtIndex:theIndex];

        // Set up NSStrings to hold keys and values.  First, how many are there?
        const NSUInteger theCount = [theDict count];
        NSString *keys[theCount];
        NSString *values[theCount];

        // Get the keys and values from the CFDictionary.  Note that because
        // we're using the "GetKeysAndValues" function, you don't need to
        // release keys or values.  It's the "Get Rule" and only applies to
        // CoreFoundation objects.
        [theDict getObjects:values andKeys:keys];

        // Set the address label's text.
        NSString *address;
        address = [NSString stringWithFormat:@"%@, %@, %@, %@ %@",
                   [theDict objectForKey:(NSString *)kABPersonAddressStreetKey],
                   [theDict objectForKey:(NSString *)kABPersonAddressCityKey],
                   [theDict objectForKey:(NSString *)kABPersonAddressStateKey],
                   [theDict objectForKey:(NSString *)kABPersonAddressZIPKey],
                   [theDict objectForKey:(NSString *)kABPersonAddressCountryKey]];

        self.addressLabel.text = address;

        // Return to the main view controller.
        [ self dismissModalViewControllerAnimated:YES ];
        return NO;
    }

    // If they didn't pick an address, return YES here to keep going.
    return YES;
}</strong></pre>
<p><strong></strong></p></blockquote>
<p>Let’s go through that in more detail.  The method gives us the following information: an <em>ABRecordRef</em> of the person we’ve selected, an <em>ABPropertyID</em> of the property slected (in this case, we ensure that it’s the address) and an <em>ABMultiValueIdentifier</em> of which address we’ve selected.  It is important to note that the <em>ABPropertyID</em> is equal to <em>kABPersonAddressProperty</em> when you select any address; that is, there is only one address property.  This one address property holds the values in an <em>ABMultiValue</em>, each at a specific index.  Here are the steps we take in the code:</p>
<ol>
<li>The first thing we do is define our <em>ABMultiValue</em>, multi, and copy the contents of the selected value into it.</li>
<li>Then we define an <em>NSArray</em>, <strong>theArray</strong>, into which to copy the multiple values.  But which one do we want?</li>
<li>Each address has an identifier, which the method gives to us as identifier, but we reference them by index when getting them out of the array.  So, we need to create an index (which we’ll store as an unsigned integer), <strong>theIndex</strong>, and set it to the return value of the <code>ABMultiValueGetIndexForIdentifier</code> function.  Now that we have the index, we know which value of the array to store .  They’re stored as type <em>CFDictionary</em>, which have key-value pairs for us to use, so we define an <em>NSDictionary</em>, <strong>theDict</strong> to put them into.</li>
<li>First, we need to know how many key-value pairs there are, so we use the <code>count</code> method and store the return value in an unsigned integer, <strong>theCount</strong>.  Be sure that this variable doesn&amp;rquo;t change—you don’t want to assume that there are more members in the array than there actually are, as that can lead to nasty memory problems.  For that reason I’ve defined it as a constant.</li>
<li>Now, we define two <em>NSString</em> arrays, <strong>keys[theCount]</strong> and <strong>values[theCount]</strong>, and then we’re ready for action.</li>
<li>Next we use the <em>NSDictionary</em> <code>getObjects: andKeys:</code> function to copy the keys and values. The function copies the data, and we can construct our street address.  For the purpose of this example, I’m going to make the address a single line, but you do with it what you want.</li>
<li>Finally, we create a final <em>NSString</em> to put the formatted address into, pull the values out of the dictionary into the appropriate place, and we’re all done!</li>
</ol>
<p><strong>Update 2010-07-27:</strong> Removed <code>[ theDict release ];</code>, some bad memory management.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2009/01/21/cocoa-touch-tutorial-extract-address-book-address-values-on-iphone-os/feed/</wfw:commentRss>
		<slash:comments>41</slash:comments>
		</item>
	</channel>
</rss>
