<?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>Lap Cat Software Blog &#187; Cocoa</title>
	<atom:link href="http://lapcatsoftware.com/blog/category/cocoa/feed/" rel="self" type="application/rss+xml" />
	<link>http://lapcatsoftware.com/blog</link>
	<description>Coding under the close supervision of cats</description>
	<lastBuildDate>Sat, 24 Jul 2010 13:30:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Local variables are free</title>
		<link>http://lapcatsoftware.com/blog/2009/12/19/local-variables-are-free/</link>
		<comments>http://lapcatsoftware.com/blog/2009/12/19/local-variables-are-free/#comments</comments>
		<pubDate>Sat, 06 Feb 2010 16:30:13 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://lapcatsoftware.com/blog/?p=236</guid>
		<description><![CDATA[This is part II of my irregularly scheduled series on compiler optimization. In part I, I explained how the compiler can optimize away return statements, resulting in missed breakpoints. My given workaround to that problem, though effective, was very ugly and architecture-dependent, much like Cowboys Stadium. (gdb) break *0x00001fc5 if $eax != 0 Although there&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>This is part II of my irregularly scheduled series on compiler optimization. In <a href="http://lapcatsoftware.com/blog/2009/11/16/why-did-my-breakpoint-not-get-hit/" title="Why did my breakpoint not get hit?">part I</a>, I explained how the compiler can optimize away <code>return</code> statements, resulting in missed breakpoints. My given workaround to that problem, though effective, was very ugly and architecture-dependent, much like Cowboys Stadium.</p>
<pre><code>(gdb) break *0x00001fc5 if $eax != 0</code></pre>
<p>Although there&#8217;s not much we can do to prevent the compiler optimization, we can greatly simplify our conditional breakpoint. I had suggested rewriting the source code, which was awe-inspiringly prescient, because that&#8217;s what I&#8217;m going to do now. Here&#8217;s the original code:</p>
<pre><code>8	if (ShouldReturn())
9		return;</code></pre>
<p>And here&#8217;s the revised code:</p>
<pre><code>8	int localVar = ShouldReturn();
9	if (localVar)
10		return;</code></pre>
<p>The <code>return</code> at line 10 will still be optimized away. However, the revised code allows us to set a simple breakpoint at line 9 that will stop when we want:</p>
<pre><code>(gdb) break 9 if localVar != 0</code></pre>
<p>No knowledge of the architecture, machine registers, or assembly language is required.</p>
<p>From the beginning of time (January 1970, of course), programmers have struggled over coding style. Objective-C programmers, for example, expend undue effort arranging their brackets. (I have <code>[NSMutableArray array]</code> going to the Final Four.) For some, bracket-making becomes a kind of game or contest.</p>
<pre><code>[[[[[[[[[[[[[See how] many] method] calls] we] can] fit] on] one] line] of] source] code];</code></pre>
<p>I&#8217;ve changed my coding style over the years, but I&#8217;ve settled on one fundamental principle: write your code so that it&#8217;s easy to debug. All your fancy margin-aligning isn&#8217;t going to help when you need to figure out why your app keeps exploding. If you have nested method calls on one line of code, you can&#8217;t easily set a breakpoint in the middle. That&#8217;s why I prefer as much as possible to have only one method call per line of code, and create a local variable to store the return value.</p>
<p>There is a misconception that local variables are expensive, in terms of either computation or memory. The truth is that local variables are very cheap, the value meals of the computing world. (Would you like trans fat with your saturated fat?) It only takes one machine instruction to store a pointer address to a local variable. One machine instruction is really quite fast, about as fast as you can get &mdash; at least with restrictor plates. With regard to memory, local variables only take up stack space. To create a local variable, you simply move the stack a little. When the method or function returns, the stack is moved back, and thereby the space reserved for local variables is automatically recovered. Of course, you don&#8217;t want to create large C arrays on the stack, but a pointer to an Objective-C object only takes 4 bytes on the stack for 32-bit, 8 bytes for 64-bit. The default 32-bit stack size is 8MB, so you&#8217;re not going to run out of space unless you have deeply recursive calls.</p>
<p>Even these small costs are only relevant in the context of your app&#8217;s unoptimized, debug configuration. For your customers, on the other hand, local variables are free. As in Mumia, or Bird. When you compile your app using the release configuration, the local variables disappear, the compiler optimizes them away. (By the way, this is one of the reasons that debugging the release build of your app can be a frustrating and/or wacky experience.) To see the optimization in action, let&#8217;s consider some sample code:</p>
<pre><code>1  #import &lt;Foundation/Foundation.h&gt;
2
3  @interface MyObject : NSObject {}
4  @end
5
6  @implementation MyObject
7
8  -(NSString *)myDirectProcessName {
9  	return [[[NSProcessInfo processInfo] processName] lowercaseString];
10 }
11
12 -(NSString *)myRoundaboutProcessName {
13 	NSString *myRoundaboutProcessName = nil;
14 	NSProcessInfo *processInfo = [NSProcessInfo processInfo];
15 	NSString *processName = [processInfo processName];
16 	NSString *lowercaseString = [processName lowercaseString];
17 	myRoundaboutProcessName = lowercaseString;
18 	return myRoundaboutProcessName;
19 }
20
21 @end
22
23 int main(int argc, const char *argv[]) {
24 	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
25 	MyObject *myObject = [[[MyObject alloc] init] autorelease];
26 	NSLog(@"My direct process name: %@", [myObject myDirectProcessName]);
27 	NSLog(@"My roundabout process name: %@", [myObject myRoundaboutProcessName]);
28 	[pool release];
29 	return 0;
30 }</code></pre>
<p>The above code is obviously contrived and useless. It only has value for explanatory purposes, and perhaps in the app store for $0.99. The methods <code>-myRoundaboutProcessName</code> and <code>-myDirectProcessName</code> do the same thing, the former with and the latter without local variables. Here&#8217;s the i386 disassembly for the methods when compiled using the debug configuration:</p>
<pre><code>-[MyObject myDirectProcessName]:
00001d2a	nop
00001d2b	nop
00001d2c	nop
00001d2d	nop
00001d2e	nop
00001d2f	nop
00001d30	pushl	%ebp
00001d31	movl	%esp,%ebp
00001d33	pushl	%ebx
00001d34	subl	$0x14,%esp
00001d37	calll	0x00001d3c
00001d3c	popl	%ebx
00001d3d	leal	0x000012e8(%ebx),%eax
00001d43	movl	(%eax),%eax
00001d45	movl	%eax,%edx
00001d47	leal	0x000012e4(%ebx),%eax
00001d4d	movl	(%eax),%eax
00001d4f	movl	%eax,0x04(%esp)
00001d53	movl	%edx,(%esp)
00001d56	calll	0x0000400a	; symbol stub for: _objc_msgSend
00001d5b	movl	%eax,%edx
00001d5d	leal	0x000012e0(%ebx),%eax
00001d63	movl	(%eax),%eax
00001d65	movl	%eax,0x04(%esp)
00001d69	movl	%edx,(%esp)
00001d6c	calll	0x0000400a	; symbol stub for: _objc_msgSend
00001d71	movl	%eax,%edx
00001d73	leal	0x000012dc(%ebx),%eax
00001d79	movl	(%eax),%eax
00001d7b	movl	%eax,0x04(%esp)
00001d7f	movl	%edx,(%esp)
00001d82	calll	0x0000400a	; symbol stub for: _objc_msgSend
00001d87	addl	$0x14,%esp
00001d8a	popl	%ebx
00001d8b	leave
00001d8c	ret
-[MyObject myRoundaboutProcessName]:
00001d8d	nop
00001d8e	nop
00001d8f	nop
00001d90	nop
00001d91	nop
00001d92	nop
00001d93	pushl	%ebp
00001d94	movl	%esp,%ebp
00001d96	pushl	%ebx
00001d97	subl	$0x24,%esp
00001d9a	calll	0x00001d9f
00001d9f	popl	%ebx
00001da0	movl	$0x00000000,0xe8(%ebp)
00001da7	leal	0x00001285(%ebx),%eax
00001dad	movl	(%eax),%eax
00001daf	movl	%eax,%edx
00001db1	leal	0x00001281(%ebx),%eax
00001db7	movl	(%eax),%eax
00001db9	movl	%eax,0x04(%esp)
00001dbd	movl	%edx,(%esp)
00001dc0	calll	0x0000400a	; symbol stub for: _objc_msgSend
00001dc5	movl	%eax,0xec(%ebp)
00001dc8	movl	0xec(%ebp),%edx
00001dcb	leal	0x0000127d(%ebx),%eax
00001dd1	movl	(%eax),%eax
00001dd3	movl	%eax,0x04(%esp)
00001dd7	movl	%edx,(%esp)
00001dda	calll	0x0000400a	; symbol stub for: _objc_msgSend
00001ddf	movl	%eax,0xf0(%ebp)
00001de2	movl	0xf0(%ebp),%edx
00001de5	leal	0x00001279(%ebx),%eax
00001deb	movl	(%eax),%eax
00001ded	movl	%eax,0x04(%esp)
00001df1	movl	%edx,(%esp)
00001df4	calll	0x0000400a	; symbol stub for: _objc_msgSend
00001df9	movl	%eax,0xf4(%ebp)
00001dfc	movl	0xf4(%ebp),%eax
00001dff	movl	%eax,0xe8(%ebp)
00001e02	movl	0xe8(%ebp),%eax
00001e05	addl	$0x24,%esp
00001e08	popl	%ebx
00001e09	leave
00001e0a	ret</code></pre>
<p>As expected, <code>-myRoundaboutProcessName</code> makes more room on the stack than <code>-myDirectProcessName</code>:</p>
<pre><code>00001d34	subl	$0x14,%esp
00001d97	subl	$0x24,%esp</code></pre>
<p>At <code>00001da0</code>, <code>-myRoundaboutProcessName</code> sets the value of the local variable to <code>nil</code>, as in line 13 of the source code. The interesting differences, though, are immediately after the calls to <code>objc_msgSend()</code>. By the standard ABI, the register <code>eax</code> contains the return value of <code>objc_msgSend()</code>. In <code>-myDirectProcessName</code>, the value in <code>eax</code> is simply moved to the register <code>edx</code>:</p>
<pre><code>00001d5b	movl	%eax,%edx</code></pre>
<p>In contrast, <code>-myRoundaboutProcessName</code> first stores the value on the stack before moving it to <code>edx</code>. The address on the stack is the space reserved for the local variable:</p>
<pre><code>00001dc5	movl	%eax,0xec(%ebp)
00001dc8	movl	0xec(%ebp),%edx</code></pre>
<p>After the final <code>objc_msgSend()</code> call, <code>-myDirectProcessName</code> doesn&#8217;t bother to do much, because the return value in <code>eax</code> will become the return value of the whole method. In <code>-myRoundaboutProcessName</code>, it needs to store values in local variables as in lines 16 and 17 of the source code:</p>
<pre><code>00001df9	movl	%eax,0xf4(%ebp)
00001dfc	movl	0xf4(%ebp),%eax
00001dff	movl	%eax,0xe8(%ebp)
00001e02	movl	0xe8(%ebp),%eax</code></pre>
<p>So that&#8217;s how the methods differ in the unoptimized build. Now let&#8217;s see what happens when we use the release configuration. Here&#8217;s the optimized disassembly for <code>-myDirectProcessName</code>:</p>
<pre><code>-[MyObject myDirectProcessName]:
00001dce	pushl	%ebp
00001dcf	movl	%esp,%ebp
00001dd1	subl	$0x18,%esp
00001dd4	movl	0x00003000,%eax
00001dd9	movl	%eax,0x04(%esp)
00001ddd	movl	0x0000302c,%eax
00001de2	movl	%eax,(%esp)
00001de5	calll	0x0000400a	; symbol stub for: _objc_msgSend
00001dea	movl	0x00003004,%edx
00001df0	movl	%edx,0x04(%esp)
00001df4	movl	%eax,(%esp)
00001df7	calll	0x0000400a	; symbol stub for: _objc_msgSend
00001dfc	movl	0x00003008,%edx
00001e02	movl	%edx,0x0c(%ebp)
00001e05	movl	%eax,0x08(%ebp)
00001e08	leave
00001e09	jmpl	0x0000400a	; symbol stub for: _objc_msgSend</code></pre>
<p>The optimized method is significantly shorter, as expected from the compiler option <code>-Os</code>. First, you&#8217;ll notice that all those pesky <code>nop</code> instructions have been deleted. Stallman put them in unoptimized builds just to annoy us. (Or they may have been for Fix and Continue, but I always assume the worst.) There are additional optimizations as well that I won&#8217;t belabor here, because I&#8217;m eager to get to the climax. (Sorry, dear.) For your enlightenment and enjoyment, here&#8217;s the optimized disassembly for <code>-myRoundaboutProcessName</code>:</p>
<pre><code>-[MyObject myRoundaboutProcessName]:
00001e0e	pushl	%ebp
00001e0f	movl	%esp,%ebp
00001e11	subl	$0x18,%esp
00001e14	movl	0x00003000,%eax
00001e19	movl	%eax,0x04(%esp)
00001e1d	movl	0x0000302c,%eax
00001e22	movl	%eax,(%esp)
00001e25	calll	0x0000400a	; symbol stub for: _objc_msgSend
00001e2a	movl	0x00003004,%edx
00001e30	movl	%edx,0x04(%esp)
00001e34	movl	%eax,(%esp)
00001e37	calll	0x0000400a	; symbol stub for: _objc_msgSend
00001e3c	movl	0x00003008,%edx
00001e42	movl	%edx,0x0c(%ebp)
00001e45	movl	%eax,0x08(%ebp)
00001e48	leave
00001e49	jmpl	0x0000400a	; symbol stub for: _objc_msgSend</code></pre>
<p>Identical! Ah, that&#8217;s nice. Smoke &#8216;em if you got &#8216;em.</p>
<p>In conclusion, feel free to sprinkle, pepper, dash, or even drown your code with local variables. And with the engineering hours of debugging time you save, get me a nice (not free) present. I&#8217;m partial to flavored coffee and unflavored MacBooks.</p>
]]></content:encoded>
			<wfw:commentRss>http://lapcatsoftware.com/blog/2009/12/19/local-variables-are-free/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vienna 2.3.2 security update</title>
		<link>http://lapcatsoftware.com/blog/2009/07/27/vienna-2-3-2-security-update/</link>
		<comments>http://lapcatsoftware.com/blog/2009/07/27/vienna-2-3-2-security-update/#comments</comments>
		<pubDate>Sat, 03 Oct 2009 15:36:05 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Vienna]]></category>

		<guid isPermaLink="false">http://lapcatsoftware.com/blog/?p=189</guid>
		<description><![CDATA[I&#8217;ve just released the security update Vienna 2.3.2. Security is no laughing matter, so all Vienna users need to update to version 2.3.2. Release notes are here. The technical details of the vulnerability are instructive. The problem was this line of code: returnCode = NSRunAlertPanel(alertTitle, alertBody, NSLocalizedString(@"Delete", nil), NSLocalizedString(@"Cancel", nil), nil); Well, that&#8217;s not entirely [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just released the security update Vienna 2.3.2. Security is no laughing matter, so all Vienna users need to update to version 2.3.2. Release notes are <a href="http://forums.cocoaforge.com/viewtopic.php?f=18&amp;t=20567" title="Vienna 2.3.2 Security Update">here</a>.</p>
<p>The technical details of the vulnerability are instructive. The problem was this line of code:</p>
<pre><code>returnCode = NSRunAlertPanel(alertTitle, alertBody, NSLocalizedString(@"Delete", nil), NSLocalizedString(@"Cancel", nil), nil);</code></pre>
<p>Well, that&#8217;s not entirely true. The problem was that line combined with certain assignments of <code>alertBody</code>, for example:</p>
<pre><code>alertBody = [NSString stringWithFormat:@"Are you sure you want to unsubscribe from \"%@\"? This operation will delete all cached articles.", [folder name]];</code></pre>
<p>By default, the value of <code>[folder name]</code> comes from a most trustworthy source: the internet. If, by chance or design, the name contains conversion specifiers, you&#8217;re in big trouble. For a discussion of this kind of vulnerability, see Apple&#8217;s <a href="http://developer.apple.com/documentation/Security/Conceptual/SecureCodingGuide/Articles/ValidatingInput.html" title="Secure Coding Guide: Validating Input">Secure Coding Guide</a>. The Secure Coding Guide is a must read for Mac Developers. (I also recommend <a href="http://www.amazon.com/George-Orwell-Signet-Classic-August/dp/B001PKXOA2/" title="George Orwell's 1984">this</a>. Tell them Jeff sent you.)</p>
<p>One simple fix for the vulnerability is as follows:</p>
<pre><code>returnCode = NSRunAlertPanel(alertTitle, @"%@", NSLocalizedString(@"Delete", nil), NSLocalizedString(@"Cancel", nil), nil, alertBody);</code></pre>
<p>With this fix, the <code>alertBody</code> string &mdash; which contains the unvalidated folder name &mdash; is no longer treated as a format string.</p>
<p>You need to be very careful about using <code>NSRunAlertPanel()</code> and similar functions. Unfortunately, the <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Miscellaneous/AppKit_Functions/Reference/reference.html#//apple_ref/c/func/NSRunAlertPanel" title="Application Kit Functions Reference">API and documentation</a> are quite bad. The Discussion doesn&#8217;t even mention that the second argument is a format string; for that, you have to read the documentation for <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Miscellaneous/AppKit_Functions/Reference/reference.html#//apple_ref/c/func/NSBeginAlertSheet" title="Application Kit Functions Reference">another function</a>. Furthermore, it&#8217;s absolutely insane to put three unrelated items between the format string and the optional arguments for the format string.</p>
<p>As you know, however, you go to war with the API you have, not the API you might want or wish to have at a later time.</p>
]]></content:encoded>
			<wfw:commentRss>http://lapcatsoftware.com/blog/2009/07/27/vienna-2-3-2-security-update/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Radar Bug Friday: Bonus Edition</title>
		<link>http://lapcatsoftware.com/blog/2009/03/13/radar-bug-friday-bonus-edition/</link>
		<comments>http://lapcatsoftware.com/blog/2009/03/13/radar-bug-friday-bonus-edition/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 15:15:51 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://lapcatsoftware.com/blog/?p=126</guid>
		<description><![CDATA[Though Apple Bug Friday has gone the way of Rip and Robert Van Winkle, I&#8217;m bringing it back for one last, glorious, remunerative show. Opening act: some weird dancing fool who people last admired in the 80s. Take your choice. The continuing failure of Apple to provide a searchable bug database has forced developers to [...]]]></description>
			<content:encoded><![CDATA[<p>Though Apple Bug Friday has gone the way of Rip and Robert Van Winkle, I&#8217;m bringing it back for one last, glorious, remunerative show. Opening act: some weird dancing fool who people last admired in the 80s. Take your choice.</p>
<p>The continuing failure of Apple to provide a searchable bug database has forced developers to take matters into their own hands. Witness <a href="http://openradar.appspot.com/" title="Open Radar">Open Radar</a>. I&#8217;ve never been one to join any club that would have me as a member &mdash; nor have I been one to be invited to any clubs &mdash; so I&#8217;ve decided to host <a href="http://lapcatsoftware.com/rdar/index.html" title="Radar Problems">my own list of bugs.</a> Keep in mind that these are not all of the Radar bugs I&#8217;ve ever filed. They&#8217;re not even all of my currently unfixed bugs. They are, however, a very large subset of my currently unfixed bugs. (I&#8217;d say the cardinality is somewhere between aleph-null and aleph-one.)</p>
<p>For legal, moral, and comical reasons, I&#8217;ve edited the bugs to remove confidential information. I&#8217;ve also left out the embarrassing nude photos I attach for ADC. (I would stop uploading them, but engineering always requests more.) I hope that you find these bugs useful and also enjoy reading them as much as I enjoyed writing them. In fact, it&#8217;s a metaphysical certainty that you will enjoy reading them at least that much.</p>
<p>After imparting this vital information, I leave you to go in, through, and beyond &hellip; for coffee and a donut.</p>
]]></content:encoded>
			<wfw:commentRss>http://lapcatsoftware.com/blog/2009/03/13/radar-bug-friday-bonus-edition/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>dSYM in your bundle or just happy to see me</title>
		<link>http://lapcatsoftware.com/blog/2009/01/20/dsym-in-your-bundle-or-just-happy-to-see-me/</link>
		<comments>http://lapcatsoftware.com/blog/2009/01/20/dsym-in-your-bundle-or-just-happy-to-see-me/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 15:15:36 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://lapcatsoftware.com/blog/?p=111</guid>
		<description><![CDATA[It&#8217;s been a while since I posted last. Rest assured that I did survive the Y2K9 disaster, though not unscathed. Since bloggers and other entertainers &#8212; such as Brian Williams &#8212; are required by law to offer a retrospective at the end of a year, I&#8217;ve been scanning the Top 10 lists of Top 10 [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since I posted last. Rest assured that I did survive the Y2K9 disaster, though not unscathed. Since bloggers and other entertainers &mdash; such as Brian Williams &mdash; are required by law to offer a retrospective at the end of a year, I&#8217;ve been scanning the Top 10 lists of Top 10 lists of things that we have gained and lost in 2008. Next to our collective sanity, the most significant loss of the year was <a href="http://lapcatsoftware.com/blog/2008/03/09/stabs-is-deprecated/" title="Stabs is deprecated">STABS</a>. Actually, it wasn&#8217;t so much lost as deprecated. This means that we can&#8217;t expect any new features (or bugs!), and support for STABS debugging symbols may disappear in some future operating system, say, Windows -400. (I assume that the countdown of version numbers from 95 to 7 is intended to accurately represent the software&#8217;s regression.) In the transition from STABS to DWARF, it was thought (by the people who matter, viz., me) that we also lost the ability to ship debugging symbols with our apps. Luckily, it was discovered (again, by the people who matter) that we did not lose this ability.</p>
<p>Developers sometimes need to give users a debug version of an application. For example, a user may be experiencing an exception or crash that the developer cannot reproduce. Including debugging symbols with the app allows the reports to be fully symbolized. With STABS, the symbols reside within the app&#8217;s executable, so shipping them is trivial. The DWARF with dSYM format, on the other hand, puts the debugging symbols in a separate file. (To be accurate, a separate file within a separate bundle, but we&#8217;ll ignore that fact for this sentence.) By default, Xcode creates <code>MyApp.app.dSYM</code> in the same folder as <code>MyApp.app</code>, and indeed, Leopard&#8217;s crash reporter can locate <code>MyApp.app.dSYM</code> in the same folder as <code>MyApp.app</code> regardless of which folder they&#8217;re in on disk. Theoretically, then, you could have the user put a <code>.dSYM</code> in the same folder as the app. However, making the user do this would be, in a word, lame. In two words, pretty lame. Moreover, it doesn&#8217;t work at all on Tiger. Pretty, pretty lame.</p>
<p>When I face an insoluble problem, my tendency is to step back and get philosophical. Why do I exist? Why does the universe hate me? Who was the real Darrin? More to the point: what is an app? Essentially, an app is a command-line tool in a box with a pretty bow. (Another iSweater, just what I needed!) An app&#8217;s main executable file is located in the directory <code>Contents/MacOS</code> of the <code>.app</code> bundle. You can even launch an app from the command line, e.g.,</p>
<pre><code>/Applications/Safari.app/Contents/MacOS/Safari</code></pre>
<p>assuming that you haven&#8217;t deleted Safari for security reasons. So how does this information help us? It doesn&#8217;t &mdash; I&#8217;m just killing time here. However, it&#8217;s worth noting that if you build the Release configuration of a command-line tool project, Xcode by default creates <code>MyTool.dSYM</code> in the same folder as <code>MyTool</code>. In both Leopard and Tiger, the crash reporter can locate the <code>.dSYM</code> there. Thus, you would expect that the crash reporter can also locate <code>MyApp.app/Contents/MacOS/MyApp.dSYM</code> when your app crashes. And you would be right! (Of course, you would expect this because I just told you, whereas originally you would have expected to try a bunch of stuff and fail, like putting <code>MyApp.app.dSYM</code> in <code>MyApp.app/Contents/MacOS</code>.)</p>
<p>The beauty of this technique is that it works not only for the app&#8217;s main executable but also for other embedded executables such dynamic libraries and frameworks. When a crash occurs involving <code>MyFramework.framework</code>, the crash reporter will find</p>
<pre><code>MyApp.app/Contents/Frameworks/MyFramework.framework/Versions/A/MyFramework.dSYM</code></pre>
<p>You can build the framework in a separate Xcode project and copy the product along with its embedded <code>dSYM</code> into your app&#8217;s bundle, and the symbols will be found at crashtime. (That&#8217;s runtime with a bang.) In Tiger, the line numbers of the source code files can sometimes be a little off in the crash reports; this may be due to bugs in the handling of stripped binaries by <code>atos</code>, which I mentioned in my <a href="http://lapcatsoftware.com/blog/2008/03/09/stabs-is-deprecated/" title="Stabs is deprecated">earlier post</a>.</p>
<p>Now that we know where to put the debugging symbols in the app bundle, how do we get them there? Manual copying is unthinkable (like giving David Pogue a copy of OS X GM before ADC members, or putting Leon Panetta in charge of the CIA). If your entire build process is not automated, you should give up software development immediately and look for another career; I recommend professional ice dancing. You could write a shell script to copy <code>MyApp.app.dSYM</code> from the <code>build</code> directory, but that&#8217;s only slightly less annoying than having your users copy it to <code>/Applications</code>, because it&#8217;s something that Xcode should do itself.</p>
<p>Fortunately, the  <a href="http://developer.apple.com/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/100-Build_Setting_Reference/build_setting_ref.html" title="Xcode Build Setting Reference">Xcode build setting reference</a> tells us how to configure this. Or so one <a href="http://developer.apple.com/search.php?q=DWARF_DSYM_FOLDER_PATH" title="No Results Found">would think</a>. Well, at least the relevant build settings are found in the environment variables &hellip; after you&#8217;ve written your shell script. The Xcode build transcript normally doesn&#8217;t show environment variables, but you can add a run script build phase to your target and check the option &#8220;Show environment variables in build log&#8221;. The environment variables reveal the default values for <code>DWARF_DSYM_FOLDER_PATH</code> and <code>DWARF_DSYM_FILE_NAME</code>, which Xcode uses in creating the <code>dSYM</code> file. Although you won&#8217;t find them in the target&#8217;s list of build settings, you can create them yourself in the User-Defined section. To embed the <code>dSYM</code> within the app bundle, just set <code>DWARF_DSYM_FOLDER_PATH</code> to <code>$(CONFIGURATION_BUILD_DIR)/$(EXECUTABLE_FOLDER_PATH)</code> and <code>DWARF_DSYM_FILE_NAME</code> to <code>$(EXECUTABLE_NAME).dSYM</code>. These settings should work for both apps and frameworks.</p>
<p>My beard has grown longer over the course of this post, and my knees are starting to ache, so it&#8217;s time to wrap it up, tip my hat to the new year, and meet the new boss.</p>
]]></content:encoded>
			<wfw:commentRss>http://lapcatsoftware.com/blog/2009/01/20/dsym-in-your-bundle-or-just-happy-to-see-me/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Working without a nib, Part 7: The empire strikes back</title>
		<link>http://lapcatsoftware.com/blog/2008/10/20/working-without-a-nib-part-7-the-empire-strikes-back/</link>
		<comments>http://lapcatsoftware.com/blog/2008/10/20/working-without-a-nib-part-7-the-empire-strikes-back/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 15:14:55 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa]]></category>

		<guid isPermaLink="false">http://lapcatsoftware.com/blog/?p=105</guid>
		<description><![CDATA[I recently received an email from Steve Jobs. He told me that he has read all of my blog posts. I found this ridiculous, so I replied, &#8220;You&#8217;re full of it!&#8221; Shockingly, he wrote back. &#8220;Actually,&#8221; he said, &#8220;all of the new apps of the past few years are nibless.&#8221; He then described the Apple-sanctioned [...]]]></description>
			<content:encoded><![CDATA[<p>I recently received an email from Steve Jobs. He told me that he has read all of my blog posts. I found this ridiculous, so I replied, &#8220;You&#8217;re full of it!&#8221; Shockingly, he wrote back. &#8220;Actually,&#8221; he said, &#8220;all of the new apps of the past few years are nibless.&#8221; He then described the Apple-sanctioned technique of writing a nibless application.</p>
<p>In <a href="http://lapcatsoftware.com/blog/2007/06/04/working-without-a-nib-part-2-also-also-wik/" title="Working without a nib, Part 2: Also Also Wik">previous</a> <a href="http://lapcatsoftware.com/blog/2007/11/25/working-without-a-nib-part-6-working-without-a-xib/" title="Working without a nib, Part 6: Working without a xib">posts</a> of this series, I was forced to use obscure workarounds such as <code>+[NSObject poseAsClass:]</code> and <code>method_exchangeImplementations()</code> to prevent <code>NSApplicationMain()</code> from trying to load a nib. Jordy Rose of <a href="http://belkadan.com/" title="Belkadan Software">Belkadan Software</a> suggested to me that the easiest way to prevent <code>NSApplicationMain()</code> from trying to load a nib would be to avoid calling <code>NSApplicationMain()</code> at all. Instead, you would just call <code>-[NSApplication run]</code>. However, I was worried that <code>NSApplicationMain()</code> might do something else important (like phone home to get permission to launch). We don&#8217;t know, because we don&#8217;t have the source code.</p>
<p>I&#8217;m still waiting for the source code, but Steve did indicate that it was safe to skip <code>NSApplicationMain()</code>. Thus, there&#8217;s no need for tricksy runtime manipulation, except perhaps to prove your mad programming skills. Mad, that is, in the sense of having worn one ring for too long. Steve also affirmed that <a href="http://lapcatsoftware.com/blog/2007/06/17/working-without-a-nib-part-4-setapplemenu/" title="Working without a nib, Part 4: setAppleMenu">our call</a> to <code>-[NSApplication setAppleMenu:]</code>, a method that Apple removed from the API, will continue to work until there&#8217;s a replacement API. Indeed, Apple is working on some kind of replacement. Excellent! <code>/me plays air guitar.</code> So if you&#8217;re counting at home, it&#8217;s now (1) Exchange support and (2) Nibless support.</p>
<p>He didn&#8217;t mention the <b>Open Recent</b> menu, so it appears that <a href="http://lapcatsoftware.com/blog/2007/07/10/working-without-a-nib-part-5-open-recent-menu/" title="Working without a nib, Part 5: Open Recent menu">my ugly hack</a> is still required for non-document-based apps. This cannot be considered part of the Apple-sanctioned technique, though it is sanctioned by me, which is more desirable, because my approval comes in seven delicious flavors. I&#8217;ve updated Nibless for Leopard in light of Steve&#8217;s revelations and am making version 2.0 available for <a href="http://lapcatsoftware.com/downloads/NiblessLeopard2.zip" title="NiblessLeopard2.zip">immediate download</a>. This is major progress, because it already puts me two versions ahead of <a href="http://www.videolan.org/vlc/" title="VLC media player">VLC.</a></p>
<p>So long, Steve, and thanks for all the fish!</p>
]]></content:encoded>
			<wfw:commentRss>http://lapcatsoftware.com/blog/2008/10/20/working-without-a-nib-part-7-the-empire-strikes-back/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Cocoa memory management for smarties, Part 3: accessors</title>
		<link>http://lapcatsoftware.com/blog/2008/10/05/cocoa-memory-management-for-smarties-part-3-accessors/</link>
		<comments>http://lapcatsoftware.com/blog/2008/10/05/cocoa-memory-management-for-smarties-part-3-accessors/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 15:14:03 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Cocoa]]></category>

		<guid isPermaLink="false">http://lapcatsoftware.com/blog/?p=96</guid>
		<description><![CDATA[This post is not over until Minnesota Fats says it is, or until I figure out why he played in Iowa. In the meantime, let&#8217;s talk about getters and setters. A setter is distinguished by the prefix set, while a getter is distinguished by not having the prefix get. Got it? Getters and setters come [...]]]></description>
			<content:encoded><![CDATA[<p>This post is not over until Minnesota Fats says it is, or until I figure out why he played in Iowa. In the meantime, let&#8217;s talk about getters and setters. A setter is distinguished by the prefix <code>set</code>, while a getter is distinguished by not having the prefix <code>get</code>. Got it? Getters and setters come in pairs; collectively, they are commonly known as <em>accessor methods</em>, less commonly as <em>American Airlines</em> or <em>pocket rockets</em>.</p>
<p>Accessor methods provide encapsulated access to an object&#8217;s <em>instance variables</em> &mdash; <em>instancvariabls</em> for short. If your <em>instancvariabl</em> is an Objective-C object (in Freudian terms, an <code>id</code>),  your accessors should almost always look like this:</p>
<pre>
-(id) thing
{
	return [[_thing retain] autorelease];
}

-(void) setThing:(id)aThing
{
	if (_thing != aThing)
	{
		[_thing release];
		_thing = [aThing retain];
	}
}
</pre>
<p>You can <code>copy</code> rather than <code>retain</code> in <code>setThing:</code> if the class of <code>aThing</code> conforms to <code>&lt;NSCopying&gt;</code>.</p>
<p>It may seem redundant to <code>[[_thing retain] autorelease]</code> in <code>thing</code>, but this has an important purpose. (A special purpose, if you will, which you&#8217;ll want to use every chance you get.) Simply returning <code>_thing</code> in <code>thing</code> does not suffice, as the following code demonstrates.</p>
<pre>
1 id something = [myObject thing];
2 [myObject setThing:nil]; // Clear out the thing.
3 [something doSomething];
</pre>
<p>In line 3, your app will go boom. I&#8217;ve seen it argued (on bathroom stalls, for example) that the caller ought to <code>[[myObject thing] retain]</code> on line 1 because of this possibility, but that&#8217;s simply not the caller&#8217;s responsibility. It&#8217;s an implementation detail of <code>myObject</code> that <code>thing</code> returns an <em>instancvariabl</em> which <code>setThing:</code> releases. Moreover, the caller could inadvertently call <code>setThing:</code> by calling some other method that calls <code>setThing:</code> rather than by calling <code>setThing:</code> directly. With <code>[[_thing retain] autorelease]</code>, <code>thing</code> ensures that <code>_thing</code> will not be deallocated in the caller&#8217;s scope (as long as the caller doesn&#8217;t do anything stupid, like call out Minnesota Fats).</p>
<p>No discussion of accessors is complete without talking about thread safety. In order to write thread-safe accessors, you should first drink a bottle of whiskey. This is required because writing thread-safe accessors is a fool&#8217;s errand. Don&#8217;t do it. Don&#8217;t try it. Don&#8217;t even think about. Redesign your code to avoid the need for thread-safe accessors. If you feel you must, however, then you should acquaint yourself with <a href="http://developer.apple.com/technotes/tn2004/tn2123.html" title="CrashReporter">Technical Note TN2123</a>, because you&#8217;ll find yourself referring to it frequently. It&#8217;ll be like a nightmare, just getting (and setting) worse and worse. But at least the salad dressing will be good.</p>
]]></content:encoded>
			<wfw:commentRss>http://lapcatsoftware.com/blog/2008/10/05/cocoa-memory-management-for-smarties-part-3-accessors/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Cocoa memory management for smarties, Part 2: working with a nib</title>
		<link>http://lapcatsoftware.com/blog/2008/08/25/cocoa-memory-management-for-smarties-part-2-working-with-a-nib/</link>
		<comments>http://lapcatsoftware.com/blog/2008/08/25/cocoa-memory-management-for-smarties-part-2-working-with-a-nib/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 15:17:22 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Vienna]]></category>

		<guid isPermaLink="false">http://lapcatsoftware.com/blog/?p=83</guid>
		<description><![CDATA[Well, it&#8217;s back to work for the moment. I was offered the VP slot, but I had to turn it down because they refused to accept the NDA: my name would be on the ticket, but nobody could talk about me publicly. Also, they wouldn&#8217;t get rid of the brown M&#38;Ms. I am waiting for [...]]]></description>
			<content:encoded><![CDATA[<p>Well, it&#8217;s back to work for the moment. I was offered the VP slot, but I had to turn it down because they refused to accept the NDA: my name would be on the ticket, but nobody could talk about me publicly. Also, they wouldn&#8217;t get rid of the brown M&amp;Ms. I am waiting for an offer by email from another guy, but I don&#8217;t hold out much hope, since I&#8217;m also waiting for him to learn how to use email.</p>
<p>In <a href="http://lapcatsoftware.com/blog/2008/07/28/cocoa-memory-management-for-smarties-part-1-release-me-not/" title="Cocoa memory management for smarties, Part 1: release me not">part 1 of this series</a> I talked about Cocoa memory management. For a summary of that post, load it in your browser, select all, and pass it to the Summarize system service. And now for something completely the same, in part 2 I&#8217;m going to talk about Cocoa memory management. As you all know, I love nibs. I find them to be a very human-friendly interface, much like the gom jabbar. A nib file contains archived Objective-C objects that are instantiated when the nib is instantiated, so their memory needs to be managed just as objects instantiated programmatically. Fortunately, if the nib File&#8217;s Owner is an <code>NSWindowController</code> or (new in Leopard) <code>NSViewController</code>, the File&#8217;s Owner takes care of the memory management automatically. Otherwise, it&#8217;s your job.</p>
<p>According to the <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/chapter_3_section_3.html#//apple_ref/doc/uid/10000051i-CH4-SW6" title="Nib Objet Retention">documentation</a>, <q>Objects in a nib file are initially created with a retain count of 1. As it rebuilds the object hierarchy, however, Cocoa autoreleases any objects that have a parent or owning object, such as views nested inside view hierarchies. By the time the nib-loading code is complete, only the top-level objects in the nib file have a positive retain count and no owning object. This makes the top-level objects a potential memory leak if your code does not assume responsibility for them.</q> If you look at your nib with the icon view in Interface Builder, the top-level objects consist of everything except the proxy objects such as File&#8217;s Owner, First Responder, and (new in Leopard) Application. Thus, top-level objects include not only windows but also contextual menus, array controllers, etc. For example, <a href="http://vienna-rss.sourceforge.net/vienna2.php" title="Vienna">Vienna&#8217;s</a> <code>MainMenu.nib</code>, pictured below, contains 14 top-level objects. (Kids, don&#8217;t try this at home.)</p>
<div><img src="http://lapcatsoftware.com/downloads/img/vienna-mainmenu-nib.png" alt="MainMenu.nib"/></div>
<p>By the way, the <code>MainMenu.nib</code> file, or whatever is specified by <code>NSMainNibFile</code> in <code>Info.plist</code>, is actually a special case, because the File&#8217;s Owner is <code>NSApplication</code> (or whatever is specified by <code>NSPrincipalClass</code>). You don&#8217;t need to worry about its memory management either, although the objects in the nib will usually remain in memory for the lifetime of the app. On termination, <code>NSApplication</code> may or may not choose to <code>release</code> those objects, as it pleases, so don&#8217;t depend on any code in <code>dealloc</code>. Cleaning up memory on app termination is like sweeping your floor right before a tornado hits.</p>
<p>In order to manage the memory of the nib&#8217;s top-level objects, you&#8217;ll need a reference to them. The method <code>-[NSNib instantiateNibWithOwner: topLevelObjects:]</code> is handy in this respect. The <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSNib_Class/Reference/Reference.html#//apple_ref/occ/instm/NSNib/instantiateNibWithOwner:topLevelObjects:" title="NSNib Class Reference">documentation</a> of the <code>(NSArray **) topLevelObjects</code> argument may be a little confusing, though: <q>On input, a variable capable of holding an <code>NSArray</code> object. On output, this variable contains an autoreleased <code>NSArray</code> object containing the top-level objects from the nib file.</q> Although the <code>NSArray</code> is autoreleased, the top-level objects themselves are not. Each object in the <code>NSArray</code> will have a retain count of at least 2. Thus, after the <code>NSArray</code> is deallocated and releases its objects, they will each still have a retain count of at least 1. A typical way to handle this is as follows.</p>
<pre><code>
@interface MyObject : NSObject
{ NSArray * _topLevelObjects; }
@end

@implementation MyObject

-(id) init
{
	self = [super init];
	if (self)
	{
		NSNib * nib = [[[NSNib alloc] initWithNibNamed:@"MyNib" bundle:nil] autorelease];
		if (nib &amp;&amp; [nib instantiateNibWithOwner:self topLevelObjects:&amp;_topLevelObjects])
		{
			// The array is autoreleased, so we need to retain it.
			// Release the objects now so that they'll be deallocated along with the array.
			[[_topLevelObjects retain] makeObjectsPerformSelector:@selector(release)];
		}
	}
	return self;
}

-(void) dealloc
{
	[_topLevelObjects release];
	[super dealloc];
}

@end
</code></pre>
<p>If you use a different method to instantiate the nib, such as <code>+[NSBundle loadNibNamed:owner:]</code>, or if you don&#8217;t want to keep an array of the top-level objects, you&#8217;ll need to create an <code>IBOutlet</code> for each top-level object in the nib and release the objects in <code>dealloc</code> along with any other ivars.</p>
<p>A major caveat for do-it-yourself nib loading is that even if you take care to release your top-level objects, you can still get a memory leak if you use Cocoa bindings in your nib. This occurs when an object in the nib binds to the File&#8217;s Owner. The File&#8217;s Owner never gets deallocated in this case, and thus neither do the top-level objects. Again, <code>NSWindowController</code> and <code>NSViewController</code> already take care of this problem automatically, but you&#8217;ll need to deal with it if the File&#8217;s Owner is not one of those classes or their subclasses. Basically, there are three possible solutions:</p>
<ol>
<li>Unbind the bindings programmatically. You&#8217;ll need to do this elsewhere than the File Owner&#8217;s <code>dealloc</code>, which won&#8217;t get called unless you unbind.</li>
<li>Bind to a different object in the nib rather than to the File&#8217;s Owner.</li>
<li>Don&#8217;t use Cocoa bindings and nibs, because they&#8217;re teh suck.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://lapcatsoftware.com/blog/2008/08/25/cocoa-memory-management-for-smarties-part-2-working-with-a-nib/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Cocoa memory management for smarties, Part 1: release me not</title>
		<link>http://lapcatsoftware.com/blog/2008/07/28/cocoa-memory-management-for-smarties-part-1-release-me-not/</link>
		<comments>http://lapcatsoftware.com/blog/2008/07/28/cocoa-memory-management-for-smarties-part-1-release-me-not/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 15:12:59 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Cocoa]]></category>

		<guid isPermaLink="false">http://lapcatsoftware.com/blog/?p=76</guid>
		<description><![CDATA[If I were to offer one bit of advice to young programmers, I would say always &#8230; uh &#8230; never &#8230; forget to check your references. Not to mention your optics and your closet. Supposedly, the rules of Cocoa memory management are simple. Just set GCC_ENABLE_OBJC_GC = required and wait for the money to roll [...]]]></description>
			<content:encoded><![CDATA[<p>If I were to offer one bit of advice to young programmers, I would say always &hellip; uh &hellip; never &hellip; forget to check your references. Not to mention your optics and your closet. Supposedly, the rules of Cocoa memory management are simple. Just set <code>GCC_ENABLE_OBJC_GC = required</code> and wait for the money to roll in, right? For those who don&#8217;t enjoy the smell of Objective-C garbage collection, we have the tried-and-true manual rules. If you obtain a reference to an object by calling <code>+alloc</code>, <code>+allocWithZone:</code>, <code>+new</code>, or <code>-copy</code>, then the reference should remain valid indefinitely. A reference obtained in any other way is guaranteed to be valid only during the current event loop, so you&#8217;ll need to call <code>-retain</code> if the reference should remain valid for longer (e.g., if you want to store it in an instance variable). Each of the aforementioned method calls must be balanced at some point by a call to <code>-release</code>, if it&#8217;s safe for the object to deallocate immediately, or <code>-autorelease</code>, if you need the object to stick around until the end of the event loop.</p>
<p>In theory, these rules are foolproof. In practice, however, they&#8217;re not even expert-proof, as we see when the experts&#8217; apps unexpectedly quit. Thus, I believe that writing a series of posts exploring the subtleties of Cocoa memory management is a worthy endeavor. Moreover, I need to kill some time before football season kicks off.</p>
<p>Below is a simplified version of a crasher I once discovered and fixed. I&#8217;m only giving the bare essentials here. There was a lot of code involved, which made it more difficult to diagnose.</p>
<pre><code>
@implementation MYChild

-(void)doSomething
{
	...
	if (...)
	{
		[self setMyProperty:theValue];
	}
	if ([_myArray count] > 0)
	...
}

@end

@implementation MYParent

-(void)start
{
	...
	_myChild = [[MYChild alloc] init];
	[_myChild addObserver:self forKeyPath:@"myProperty" options:0 context:NULL];
	...
}

-(void)stop
{
	...
	[_myChild removeObserver:self forKeyPath:@"myProperty"];
	[_myChild release];
	_myChild = nil;
	...
}

-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{
	...
	[self stop];
	...
}

@end
</code></pre>
<p>Can you guess where the crash occurred? The particularly tricky part is that <code>observeValueForKeyPath:</code> is called by the Cocoa runtime rather than by the app&#8217;s own code, which means that if you&#8217;re not already aware of the key-value observer, the cause of the crash is rather mystifying.</p>
<p>My solution, by the way, was to replace <code>[_myChild release]</code> with <code>[_myChild autorelease]</code>. Ideally, you would probably access all ivars via getters and setters, but that&#8217;s a topic for a later post in this series.</p>
<p>In light of the above example, let&#8217;s now attempt to add to the rules of memory management:</p>
<ul>
<li>Rules are for suckers, simpletons, and lawyers.</li>
<li>No method is safe, only call paths are safe. You can&#8217;t look at a method in isolation and determine that it handles memory management properly. On the other hand, if you&#8217;re doing object-oriented encapsulation correctly, you shouldn&#8217;t have to worry about the implementation of other objects. The proper unit of analysis, I believe, is the entire call path within the object&#8217;s implementation.</li>
<li>Don&#8217;t release any method arguments. It&#8217;s almost always possible for the caller of <code>aMethod:</code> to have code such as <code>{ [anObject aMethod:anArgument]; [anArgument anotherMethod]; }</code>, so don&#8217;t invalidate <code>anArgument</code> during the current event loop. This is the reason why <code>-autorelease</code> was invented. (Also, it would be pretty silly to have <code>NSAutoreleasePool</code> without anything to go in the pool.</li>
</ul>
<p>As for the jello, I can explain. I was hungry and preparing for gravity to reverse.</p>
]]></content:encoded>
			<wfw:commentRss>http://lapcatsoftware.com/blog/2008/07/28/cocoa-memory-management-for-smarties-part-1-release-me-not/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Compiler indirectives and metaphorical keypaths</title>
		<link>http://lapcatsoftware.com/blog/2008/07/02/compiler-indirectives-and-metaphorical-keypaths/</link>
		<comments>http://lapcatsoftware.com/blog/2008/07/02/compiler-indirectives-and-metaphorical-keypaths/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 15:11:14 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Cocoa]]></category>

		<guid isPermaLink="false">http://lapcatsoftware.com/blog/?p=74</guid>
		<description><![CDATA[I am, like, literally ROTFRTFMIMHOLOLYMMVIIRCFUBAROTOH! [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(likeNoWay:) name:@"ROTFRTFMIMHOLOLYMMVIIRCFUBAROTOH" object:nil]; A string literal is a sequence of characters enclosed in quote-unquote &#8216;\&#8221;quotation marks\&#8221;&#8216; (wiggles index and middle fingers). In the C programming language &#8212; so-named because its inventors lacked imagination &#8212; a string literal represents an array of char terminated by a null (or [...]]]></description>
			<content:encoded><![CDATA[<p>I am, like, literally ROTFRTFMIMHOLOLYMMVIIRCFUBAROTOH!</p>
<pre><code>[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(likeNoWay:) name:@"ROTFRTFMIMHOLOLYMMVIIRCFUBAROTOH" object:nil];</code></pre>
<p>A string literal is a sequence of characters enclosed in quote-unquote &#8216;\&#8221;quotation marks\&#8221;&#8216; (wiggles index and middle fingers). In the C programming language &mdash; so-named because its inventors lacked imagination &mdash; a string literal represents an array of <code>char</code> terminated by a null (or by a comma when the feeling&#8217;s not that strong). In the Objective-C programming language &mdash; otherwise known as The O.C. &mdash; a string literal in a compiler directive (e.g., <code>@"NSBirdJustFlewIntoMyWindowException"</code>) defines a constant <code>NSString</code> object.</p>
<p>Chris Hanson and Sanjay Samani have offered some <a href="http://chanson.livejournal.com/186135.html" title="Always use notification name globals, not literal strings!">excellent advice</a> about avoiding the use of these <code>NSString</code> literals in your method calls. The problem is that the compiler will accept pretty much any directive: with Objective-C 1.0 the compiler only warns about non-ASCII characters, and with Objective-C 2.0 it doesn&#8217;t even do that (for better or worse, but that&#8217;s a subject for a different post). Thus, if you happen to misspell a notification name, you&#8217;ll never know until your app misbehaves at runtime. <q>I&#8217;m sorry, Dave, I&#8217;m afraid I can&#8217;t do that.</q></p>
<p>I recommend replacing <code>NSString</code> literals with macros or constant variables (huh?) wherever spelling matters. (Spelling matters everywhere. I&#8217;ve seen some pretty bad method names.) Here&#8217;s a little trick for handling arbitrary keypaths:</p>
<pre>
#define KEY1 @"key1"
#define KEY2 @"key2"
#define KEY3 @"key3"
#define DOT @"."

[self valueForKeyPath:KEY1 DOT KEY2 DOT KEY3];
</pre>
<p>Unfortunately, we&#8217;re still at the mercy of misspellings in nib bindings. Yet another reason to do without nibs. But that&#8217;s also a subject for a <a href="http://lapcatsoftware.com/blog/2007/05/16/working-without-a-nib-part-1/" title="Working without a nib, Part 1">different post</a> and horse of a different color (dried poop).</p>
]]></content:encoded>
			<wfw:commentRss>http://lapcatsoftware.com/blog/2008/07/02/compiler-indirectives-and-metaphorical-keypaths/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I&#8217;m a Rogue</title>
		<link>http://lapcatsoftware.com/blog/2008/06/07/im-a-rogue/</link>
		<comments>http://lapcatsoftware.com/blog/2008/06/07/im-a-rogue/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 15:10:48 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Rogue Amoeba]]></category>

		<guid isPermaLink="false">http://lapcatsoftware.com/blog/?p=72</guid>
		<description><![CDATA[I&#8217;m delighted to announce that I&#8217;ve been hired as Rogue Amoeba Employee 008. (Employee 007 is Longwell, Justin Longwell.) I&#8217;ll be working on Rogue Amoeba&#8217;s apps as a software engineer, as well as providing comic relief. Thanks to Alex, Paul, and Quentin for this once-in-a-lifetime opportunity. My coworkers at Rogue Amoeba Software, LLC include fellow [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m delighted to announce that I&#8217;ve been hired as <a href="http://www.rogueamoeba.com/utm/2008/06/06/welcome-another-new-rogue-amoeba/" title="Welcome Another New Rogue Amoeba!">Rogue Amoeba Employee 008</a>. (Employee 007 is Longwell, Justin Longwell.) I&#8217;ll be working on Rogue Amoeba&#8217;s apps as a software engineer, as well as providing comic relief. Thanks to Alex, Paul, and Quentin for this once-in-a-lifetime opportunity. My coworkers at <a href="http://rogueamoeba.com/" title="Rogue Amoeba - Quality Audio Software for Mac OS X">Rogue Amoeba Software, LLC</a> include fellow bloggers <a href="http://www.mikeash.com/?page=pyblog/" title="NSBlog">Mike Ash</a> and <a href="http://www.kickingbear.com/blog/" title="Kickingbear Blog">Guy English</a>. Together we form perhaps the most talented group of Mac programmers outside of <a href="http://www.apple.com/" title="Apple Inc.">Apple</a>. (Yes, I&#8217;m talking to you, Adobe and Microsoft.) Indeed, I haven&#8217;t seen such an array of stars in one place since the Ghostbusters music video.</p>
<p>I&#8217;ve joined Rogue Amoeba just in time to miss <a href="http://developer.apple.com/wwdc/" title="Apple Worldwide Developers Conference">WWDC &#8217;08</a>. In an <a href="http://lapcatsoftware.com/blog/2007/07/21/what-ive-been-doing-recently/" title="What I’ve been doing recently">earlier post</a>, I mentioned that I left <a href="http://www.karppinen.fi/" title="MK&amp;C">Marko Karppinen &amp; Co. LLC</a> just in time to miss WWDC &#8217;07. (I&#8217;ll make it there someday! <img src='http://lapcatsoftware.com/blog/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' />  ) The question is, what have I been doing in the meantime? Backpacking through Europe? Rotting in Gitmo? Running for President? No, I&#8217;ve been working on super-secret projects for <a href="http://francistech.com/" title="Francis Technical Services = Mac Cocoa Developers">Francis Technical Services, LLC</a>. Although FTS is a little-known company, its software is well-known, at least inside Apple. For example, FTS is responsible for Radar, the Apple-internal Cocoa app that opens when employees click on the funny-looking <a href="rdar://problem/" title="rdar problem URL">rdar://problem/</a> URLs you often see. The number at the end of the URL corresponds to the problem ID of the bugs you file on the web with <a href="https://bugreport.apple.com/" title="Apple Bug Reporter">Apple Bug Reporter</a> (also known as RadarWeb). It&#8217;s useful to have one of these URLs available when communicating with Apple engineers, because their managers forbid them from lifting a finger without a Radar problem number.</p>
<p>While at FTS, I did some bug analysis for Radar: that is, analysis of bugs in Radar&#8217;s source code, not analysis of bugs in Radar&#8217;s database, to which as a contractor I had extremely limited access. However, I mostly worked on other projects, such as Radar&#8217;s sibling app Sonar. Apple&#8217;s <a href="http://developer.apple.com/technicalsupport/" title="Developer Technical Support">DTS</a> uses Sonar to communicate with <a href="http://developer.apple.com/" title="Apple Developer Connection">ADC</a> members (such as me!). If you&#8217;ve ever seen <a href="sonr://request/" title="sonr request URL">sonr://request/</a> URLs &mdash; the Mighty Quinn provides one in an <a href="http://lists.apple.com/archives/filesystem-dev/2008/Mar/msg00003.html" title="Re: Strange behavior iterating the directory tree of a volume">Apple Mailing List post</a> &mdash; those open in Sonar. (By the way, I&#8217;ve read all of your emails to DTS. No, you haven&#8217;t been accepted to the iPhone Developer Program. Stop whining.) Another project that I worked on was Merlin, an app for Apple&#8217;s Human Resources department. I think that Steve Jobs is doing an outstanding job at Apple, so before I left I used Merlin to double his annual salary.</p>
<p>I&#8217;d like to thank Dave Francis, the owner and founder of Francis Tech, for the opportunity to work there. Despite appearances, I&#8217;m not really the type to hop from job to job. I&#8217;ve just been looking for Mr. Right, LLC, a company to fall in love with, marry, and have baby apps with. (As for any other support claims, sorry Billie Jean.) I can see myself growing old with Rogue Amoeba. (Easy to see when you&#8217;re already old?) Besides, someone has to stick around and keep an eye on mikeash, stop him from taking over the world.</p>
<p>Now without further ado, please take out your credit card and buy some of our <a href="https://www.rogueamoeba.com/store/" title="Rogue Amoeba - Store">fine software</a>. As a special bonus for our Leopard customers, your purchase will be (code-)signed by your favorite Rogue Amoeba star.</p>
]]></content:encoded>
			<wfw:commentRss>http://lapcatsoftware.com/blog/2008/06/07/im-a-rogue/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
