<?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; Apple</title>
	<atom:link href="http://blog.slaunchaman.com/tag/apple/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>Apple Doesn’t Like “Die, You Gravy-Sucking Pig-Dog!”</title>
		<link>http://blog.slaunchaman.com/2010/08/19/apple-doesn%e2%80%99t-like-%e2%80%9cdie-you-gravy-sucking-pig-dog%e2%80%9d/</link>
		<comments>http://blog.slaunchaman.com/2010/08/19/apple-doesn%e2%80%99t-like-%e2%80%9cdie-you-gravy-sucking-pig-dog%e2%80%9d/#comments</comments>
		<pubDate>Thu, 19 Aug 2010 21:14:12 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[BSD]]></category>
		<category><![CDATA[Easter eggs]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[UNIX beard]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=328</guid>
		<description><![CDATA[There’s a relatively well-known Easter]]></description>
			<content:encoded><![CDATA[<p>There’s a <a href="http://www.codinghorror.com/blog/2009/01/die-you-gravy-sucking-pig-dog.html">relatively well-known</a> Easter egg in BSD’s <code>shutdown.c</code>: a function named <code>die_you_gravy_sucking_pig_dog</code> (side note: I’ve got three-to-one odds that say whoever wrote that has a huge UNIX beard). It turns out that Apple doesn’t care to have such uncouth function names floating around, so <a href="http://opensource.apple.com/source/system_cmds/system_cmds-498.2/shutdown.tproj/shutdown.c">they re-defined it</a>:</p>
<blockquote><p><code>#ifdef __APPLE__<br />
void log_and_exec_reboot_or_halt(void);<br />
#else<br />
void die_you_gravy_sucking_pig_dog(void);<br />
#endif</code></p></blockquote>
<p>Sure, it does the same thing, but I don’t think <code>log_and_exec_reboot_or_halt</code> has the same panache.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/08/19/apple-doesn%e2%80%99t-like-%e2%80%9cdie-you-gravy-sucking-pig-dog%e2%80%9d/feed/</wfw:commentRss>
		<slash:comments>0</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[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>How-To: Run a LaunchDaemon That Requires Networking</title>
		<link>http://blog.slaunchaman.com/2010/07/01/how-to-run-a-launchdaemon-that-requires-networking/</link>
		<comments>http://blog.slaunchaman.com/2010/07/01/how-to-run-a-launchdaemon-that-requires-networking/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 17:28:37 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Mac Systems Administration]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[command-line]]></category>
		<category><![CDATA[launchd]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=300</guid>
		<description><![CDATA[I’m a big fan of]]></description>
			<content:encoded><![CDATA[<p>I’m a big fan of using <a href="http://launchd.macosforge.org/">launchd</a> to automate things in Mac OS X. That serves me well, as that’s how Apple wants things done moving forward. That said, one of launchd’s biggest shortcomings is a lack of a dependency system. There is currently no way, for instance, to specify in a LaunchDaemon’s property list that the daemon requires the network to be active in order to run. This is problematic for some things, such as a script I wrote to automatically set the computer’s hostname based on the DNS server (more on that later). Luckily, Apple has already defined a function, <code>CheckForNetwork</code>, in <code>/private/etc/rc.common</code>. Here it is in all its glory:</p>
<blockquote><pre>##
# Determine if the network is up by looking for any non-loopback
# internet network interfaces.
##
CheckForNetwork()
{
	local test

	if [ -z "${NETWORKUP:=}" ]; then
		test=$(ifconfig -a inet 2>/dev/null | sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' -e '/inet/p' | wc -l)
		if [ "${test}" -gt 0 ]; then
			NETWORKUP="-YES-"
		else
			NETWORKUP="-NO-"
		fi
	fi
}</pre>
</blockquote>
<p>In your code, simply include <code>rc.common</code>, then call <code>CheckForNetwork</code> as needed. An example:</p>
<blockquote><pre>#!/bin/bash

# Example Daemon Starter
. /etc/rc.common

CheckForNetwork

while [ "${NETWORKUP}" != "-YES-" ]
do
        sleep 5
        NETWORKUP=
        CheckForNetwork
done

# Now do what you need to do.</pre>
</blockquote>
<p>Note that this will keep the script running indefinitely until <code>CheckForNetwork</code> sets <code>NETWORKUP</code> to “<code>-YES-</code>,” so if there’s a networking problem your code may never execute.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/07/01/how-to-run-a-launchdaemon-that-requires-networking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updating dyld Shared Caches with Radmind: Best Practices</title>
		<link>http://blog.slaunchaman.com/2010/06/15/updating-dyld-shared-caches-with-radmind-best-practices/</link>
		<comments>http://blog.slaunchaman.com/2010/06/15/updating-dyld-shared-caches-with-radmind-best-practices/#comments</comments>
		<pubDate>Tue, 15 Jun 2010 15:41:56 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Mac Systems Administration]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[dyld]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Radmind]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[Systems Administration]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=280</guid>
		<description><![CDATA[Similar to my last post]]></description>
			<content:encoded><![CDATA[<p>Similar to my last post about <a href="http://blog.slaunchaman.com/2010/05/27/updating-kernel-extensions-with-radmind-best-practices/">updating kernel extensions</a>, you can run into problems with Radmind due to the dyld shared cache. You may see messages like this in your system log:</p>
<blockquote><p><code>current cache invalid because /System/Library/Frameworks/WebKit.framework/Versions/A/WebKit has changed</code></p></blockquote>
<p>Running the <code>update_dyld_shared_cache</code> command will fix this, but there&#8217;s a better way. Sure, there&#8217;s almost no overhead to that command, but where&#8217;s the fun in that? Here&#8217;s a pre-apply script that will delete any shared caches that have changed, which will then be re-built at reboot.</p>
<blockquote><p><code>
<pre>#!/bin/sh

# update_dyld_caches: Inspects the applicable transcript for something that
#                     might cause a dyld cache to become outdated. If it exists,
#                     delete the cache so it's re-created at startup.

DYLD_CACHE_FOLDER="/private/var/db/dyld"
DYLD_PREFIX="dyld_shared_cache_"
ARCHITECTURES="i386 x86_64 rosetta ppc ppc64"

for arch in ${ARCHITECTURES}; do
	cache="${DYLD_CACHE_FOLDER}/${DYLD_PREFIX}${arch}"
	map="${DYLD_CACHE_FOLDER}/${DYLD_PREFIX}${arch}.map"

	if /bin/test -f "${cache}"; then
		if /bin/test -f "${map}"; then
			/bin/cat "${map}" | grep ^/ | sort --unique --ignore-case | while read line; do
				if /bin/test -n "$(grep ${line} ${1})"; then # found a match
					/bin/rm -f "${cache}"
					/bin/rm -f "${map}"
					break;
				fi
			done
		else
			# Cache exists, but there's no map.
			/bin/rm -f "${cache}"
		fi
	fi
done</pre>
<p></code></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/06/15/updating-dyld-shared-caches-with-radmind-best-practices/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updating Kernel Extensions with Radmind: Best Practices</title>
		<link>http://blog.slaunchaman.com/2010/05/27/updating-kernel-extensions-with-radmind-best-practices/</link>
		<comments>http://blog.slaunchaman.com/2010/05/27/updating-kernel-extensions-with-radmind-best-practices/#comments</comments>
		<pubDate>Thu, 27 May 2010 17:28:36 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Mac Systems Administration]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Kernel Extensions]]></category>
		<category><![CDATA[kextd]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Radmind]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[Systems Administration]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=272</guid>
		<description><![CDATA[One of the problems that]]></description>
			<content:encoded><![CDATA[<p>One of the problems that I&#8217;ve run into so far using <a href="http://www.radmind.org">Radmind</a> to manage Mac OS X—specifically, the Leopard to Snow Leopard transition—is that <code>kextd</code> helpfully starts recreating your kernel extension cache as soon as you modify anything in <code>/System/Library/Extensions</code>. This can be problematic when you&#8217;re updating core system files; as you update the 10.5 kernel extensions to their 10.6 counterparts, you don&#8217;t want the 10.5 version of <code>kextd</code> creating a cache of 10.6 kernel extensions, especially as the kernel extension cache has moved (from <code>/System/Library/Extensions.mkext</code> to <code>/System/Library/Caches/com.apple.kext.caches/</code>). So, should you handle this? My solution is to stop <code>kextd</code> if I know that I&#8217;m updating kernel extensions; that way, they won&#8217;t be re-created until reboot. Here&#8217;s the script:</p>
<p><code>/private/var/radmind/preapply/update_kernel_extensions</code>:</p>
<blockquote><p><code>
<pre>#!/bin/sh

# update_kernel_extensions: Manage the replacement of old kernel extensions.
#                           If there are updates, kill kextd and destroy the
#                           caches.

KEXT_CACHE="/System/Library/Caches/com.apple.kext.caches"
KEXT_FOLDER="/System/Library/Extensions"
KEXTD_LAUNCHD="com.apple.kextd"
SYSTEM_LAUNCHD_FOLDER="/System/Library/LaunchDaemons"

transcript="${1}"
result="${transcript}.$$"

/usr/bin/grep "${KEXT_FOLDER}" "${transcript}" > "${result}"

if test -n "${result}"; then #result is non-empty
    # Disable kextd to prevent it from recreating kernel extension caches, which
    # will be re-created at startup.
    if test -n "$(/bin/launchctl list | /usr/bin/grep ${KEXTD_LAUNCHD})"; then
        #kextd is running
        /bin/launchctl unload "${SYSTEM_LAUNCHD_FOLDER}/${KEXTD_LAUNCHD}.plist"
    fi

    # Remove kernel extension cache.
    /bin/rm -rf "${KEXT_CACHE}"
fi

rm -f "${result}"</pre>
<p></code></p></blockquote>
<p>In its present form, it only works on Snow Leopard, but I&#8217;ll be updating it to work on Leopard as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/05/27/updating-kernel-extensions-with-radmind-best-practices/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using AppleScript to Automate an iChat Video Chat</title>
		<link>http://blog.slaunchaman.com/2010/03/30/using-applescript-to-automate-an-ichat-video-chat/</link>
		<comments>http://blog.slaunchaman.com/2010/03/30/using-applescript-to-automate-an-ichat-video-chat/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 16:53:09 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Mac Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[AppleScript]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[iChat]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=256</guid>
		<description><![CDATA[I had to write a script to automatically start iChat at login and start a video chat with a specified screenname. I wanted to only start the chat if the user was online and available, and quit iChat on an error or if the chat ended.]]></description>
			<content:encoded><![CDATA[<p>I had to write a script to automatically start iChat at login and start a video chat with a specified screenname. I wanted to only start the chat if the user was online and available, and quit iChat on an error or if the chat ended. So here’s the script I have:</p>
<pre style="overflow:auto;"><strong>using terms from</strong> <em><span style="color: #0000ff;">application</span></em> "iChat"
	<strong>tell</strong> <em><span style="color: #0000ff;">application</span></em> "iChat"
		<strong><span style="color: #0000ff;">activate</span></strong>
		<span style="color: #0000ff;"><strong>log in</strong></span>
		<span style="color: #333399;"><strong>delay</strong></span> 5
		<strong>set</strong> <span style="color: #008000;">theBuddy</span> <strong>to</strong> <em><span style="color: #0000ff;">buddy</span></em> "ScreennameGoesHere" <strong>of</strong> <em><span style="color: #0000ff;">service</span></em> "AIM"
		<strong>try</strong>
			<strong>set</strong> <span style="color: #008000;">theStatus</span> <strong>to</strong> <span style="color: #333399;">status</span> <strong>of</strong> <span style="color: #008000;">theBuddy</span>
		<strong>on error</strong> <span style="color: #008000;">errmesg</span> <span style="color: #0000ff;">number</span> <span style="color: #008000;">errno</span>
			<strong>set</strong> <span style="color: #008000;">message</span> <strong>to</strong> <span style="color: #333399;"><strong>display dialog</strong></span> "The user is currently unavailable." <span style="color: #333399;">buttons</span> {"OK"}
			<strong><span style="color: #0000ff;">quit</span></strong>
			<strong>return</strong>
		<strong>end try</strong>
		<strong>if</strong> <span style="color: #008000;">theStatus</span> <strong>is</strong> <span style="color: #333399;">available</span> <strong>then</strong>
			<strong>set</strong> <span style="color: #008000;">theCapabilities</span> <strong>to get</strong> <span style="color: #0000ff;">capabilities</span> <strong>of</strong> <span style="color: #008000;">theBuddy</span>
			<strong>if</strong> (<span style="color: #008000;">theCapabilities</span> <strong>contains</strong> <span style="color: #333399;">multiperson video</span>) <strong>then</strong>
				<span style="color: #0000ff;"><strong>send</strong></span> "A user is attempting to contact you." <span style="color: #0000ff;">to</span> <span style="color: #008000;">theBuddy</span>
				<span style="color: #333399;"><strong>delay</strong></span> 2
				<strong>tell</strong> <span style="color: #0000ff;"><em>service</em></span> "AIM" <strong>to</strong> <span style="color: #0000ff;"><strong>make</strong></span> <span style="color: #0000ff;"><em>video chat</em></span> <span style="color: #0000ff;">with properties</span> {participants:<span style="color: #008000;">theBuddy</span>}
				<strong>set</strong> <span style="color: #008000;">theChat</span> <strong>to</strong> <span style="color: #333399;">result</span>
				<span style="color: #333399;"><strong>delay</strong></span> 30
				<strong>try</strong>
					<strong>set</strong> <span style="color: #008000;">theStatus</span> <strong>to the</strong> <span style="color: #333399;">av connection status</span> <strong>of</strong> <span style="color: #008000;">theChat</span>
				<strong>on error</strong> <span style="color: #008000;">errmesg</span> <span style="color: #0000ff;">number</span> <span style="color: #008000;">errno</span>
					<strong><span style="color: #0000ff;">quit</span></strong>
					<strong>return</strong>
				<strong>end try</strong>
				<strong>repeat while</strong> <span style="color: #008000;">theStatus</span> <strong>is not</strong> <span style="color: #333399;">ended</span>
					<span style="color: #333399;"><strong>delay</strong></span> 5
					<strong>try</strong>
						<strong>set</strong> <span style="color: #008000;">theStatus</span> <strong>to the</strong> <span style="color: #333399;">av connection status</span> <strong>of</strong> <span style="color: #008000;">theChat</span>
					<strong>on error</strong> <span style="color: #008000;">errmesg</span> <span style="color: #0000ff;">number</span> <span style="color: #008000;">errno</span>
						<strong><span style="color: #0000ff;">quit</span></strong>
						<strong>return</strong>
					<strong>end try</strong>
				<strong>end repeat</strong>
				<strong><span style="color: #0000ff;">quit</span></strong>
				<strong>return</strong>
			<strong>else</strong>
				<strong>set</strong> <span style="color: #008000;">message</span> <strong>to</strong> <span style="color: #333399;"><strong>display dialog</strong></span> "The user cannot video chat at this time. Please try again later." <span style="color: #333399;">buttons</span> {"OK"}
				<span style="color: #0000ff;"><strong>quit</strong></span>
				<strong>return</strong>
			<strong>end if</strong>
		<strong>else</strong>
			<strong>set</strong> <span style="color: #008000;">message</span> <strong>to</strong> <span style="color: #333399;"><strong>display dialog</strong></span> "The user is currently unavailable." <span style="color: #333399;">buttons</span> {"OK"}
			<strong><span style="color: #0000ff;">quit</span></strong>
			<strong>return</strong>
		<strong>end if</strong>
	<strong>end tell</strong>
<strong>end using terms from</strong></pre>
<p>A couple of gotchas:</p>
<ul>
<li>I tried using <span style="color: #333399;"><code>video chat</code></span> instead of <span style="color: #333399;"><code>multiperson video</code></span>, but that always returned false. I don’t know why.</li>
<li>Once the video chat has ended, you can’t poll its status (hence the <strong><code>try</code></strong> block).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/03/30/using-applescript-to-automate-an-ichat-video-chat/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>Using Apple&#8217;s SimplePing on iPhone OS</title>
		<link>http://blog.slaunchaman.com/2010/02/13/using-apples-simpleping-on-iphone-os/</link>
		<comments>http://blog.slaunchaman.com/2010/02/13/using-apples-simpleping-on-iphone-os/#comments</comments>
		<pubDate>Sat, 13 Feb 2010 19:06:48 +0000</pubDate>
		<dc:creator>Jeff Kelley</dc:creator>
				<category><![CDATA[Programming Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[ping]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://blog.slaunchaman.com/?p=203</guid>
		<description><![CDATA[If you try out of]]></description>
			<content:encoded><![CDATA[<p>If you try out of the box to compile Apple&rsquo;s &ldquo;<a href="http://developer.apple.com/mac/library/samplecode/SimplePing/">SimplePing</a>&rdquo; code sample on the iPhone OS, you&rsquo;ll wind up with a lot of errors as some files don&rsquo;t exist in those SDKs. Specifically, you need these files (you need more than <em>just</em> these files to compile, obviously, but these are the ones that aren&rsquo;t included):</p>
<ul>
<li><code>/usr/include/netinet/ip.h</code></li>
<li><code>/usr/include/netinet/in_systm.h</code></li>
<li><code>/usr/include/netinet/ip_icmp.h</code></li>
<li><code>/usr/include/netinet/ip_var.h</code></li>
</ul>
<p>So here&rsquo;s a quick Bash script that links the relevant files to your iPhone OS and iPhone Simulator SDKs:<br />
<code>
<pre>for path in /Developer/Platforms/iPhone*/Developer/SDKs/*; do
    for file in /usr/include/netinet/ip.h \
                /usr/include/netinet/in_systm.h \
                /usr/include/netinet/ip_icmp.h \
                /usr/include/netinet/ip_var.h; do
        if [ ! -f "${path}${file}" ]; then
            sudo ln "${file}" "${path}${file}"
        fi;
    done;
done</pre>
<p></code><br />
I&rsquo;ve spoken to an Apple engineer and confirmed that this is the best way to do it, as well as filed a bug, which I encourage <a href="http://bugreport.apple.com">you to do as well</a> if this annoys you.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.slaunchaman.com/2010/02/13/using-apples-simpleping-on-iphone-os/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
