<?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>Red Sweater Blog &#187; Debugging</title>
	<atom:link href="http://www.red-sweater.com/blog/category/articles/programming/debugging/feed" rel="self" type="application/rss+xml" />
	<link>http://www.red-sweater.com/blog</link>
	<description>Mac &#38; Technology Writings by Daniel Jalkut</description>
	<lastBuildDate>Tue, 17 Jan 2012 22:03:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>The Power Of Plist</title>
		<link>http://www.red-sweater.com/blog/2083/the-power-of-plist</link>
		<comments>http://www.red-sweater.com/blog/2083/the-power-of-plist#comments</comments>
		<pubDate>Wed, 03 Aug 2011 19:12:50 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Darwin]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=2083</guid>
		<description><![CDATA[Most Mac and iOS developers know that when you build an application, you advertise a number of details about the application in the &#8220;Info.plist&#8221; file, located inside the application bundle. You can examine any application on your Mac and see what kind of information the developer has conveyed about it: Navigate to a .app file [...]]]></description>
			<content:encoded><![CDATA[<p>Most Mac and iOS developers know that when you build an application, you advertise a number of details about the application in the &#8220;Info.plist&#8221; file, located inside the application bundle. You can examine any application on your Mac and see what kind of information the developer has conveyed about it:</p>
<ol>
<li>Navigate to a .app file in the Finder, e.g. /Applications/Mail.app</li>
<li>Control-click the app icon and select &#8220;Show Package Contents&#8221;</li>
<li>Navigate to Contents/Info.plist</li>
<li>Open with a plist editor or your favorite text editor.</li>
</ol>
<p>These files advertise a number of interesting attributes including the application&#8217;s official version and copyright strings. They also include important clues to the system about what kinds of files the application knows how to read and write, and what its minimum system requirements are.</p>
<h3>Minimum System Requirements</h3>
<p>Declaring the right Info.plist values not only allows a developer to control which operating systems a product should run on, but which of the application&#8217;s architectures should be considered for a particular operating system. For example, <a href="http://www.red-sweater.com/blackink/">Black Ink</a> uses a number of keyed values describing its requirements:</p>
<pre>	&lt;key&gt;LSArchitecturePriority&lt;/key&gt;
	&lt;array&gt;
		&lt;string&gt;x86_64&lt;/string&gt;
		&lt;string&gt;i386&lt;/string&gt;
		&lt;string&gt;ppc&lt;/string&gt;
	&lt;/array&gt;
	&lt;key&gt;LSMinimumSystemVersion&lt;/key&gt;
	&lt;string&gt;10.4.0&lt;/string&gt;
	&lt;key&gt;LSMinimumSystemVersionByArchitecture&lt;/key&gt;
	&lt;dict&gt;
		&lt;key&gt;i386&lt;/key&gt;
		&lt;string&gt;10.4.0&lt;/string&gt;
		&lt;key&gt;x86_64&lt;/key&gt;
		&lt;string&gt;10.6.0&lt;/string&gt;
		&lt;key&gt;ppc&lt;/key&gt;
		&lt;string&gt;10.4.0&lt;/string&gt;
	&lt;/dict&gt;
</pre>
<p>Notice the fidelity of some of these options. Black Ink is an application that is compiled with binary code for three separate architectures embedded into it: 64-bit Intel, 32-bit Intel, and 32-bit PowerPC. In order to give the user the best possible experience after they double-click the application icon, the system consults the Info.plist values to determine which binary is most appropriate to load on the current system.</p>
<p>The options for Black Ink start by indicating that all things being equal, it prefers to run as 64-bit Intel, but will settle for 32-bit Intel or PowerPC in a pinch. Next, it conveys that it should not be run on any operating system earlier than Mac OS X 10.4. Finally, it adds an additional restriction by architecture, stating that in the case of 64-bit Intel, the system should consider Mac OS X 10.6 the minimum required OS.</p>
<p>Why so picky? For example, Mac OS X 10.5 will run on computers that are new enough to support 64-bit Intel code, but the 10.5 operating environment itself doesn&#8217;t contain enough compatible libraries to make it very useful to a full-featured Cocoa application. So we need to convince the 10.5 system <em>to ignore our 64-bit Intel code.</em> And this is how it&#8217;s done.</p>
<h3>Embedding Info.plist</h3>
<p>This is all well and good for applications, but what about other code that may be run on a variety of hardware and operating systems? In particular, command-line tools do not come in the same bundled-folder format that applications do. Fortunately, Apple thought of this when they implemented support in their developer tools for embedding the contents of an Info.plist directly into the binary itself. You just have to pass the Info.plist path to Apple&#8217;s linker tool when it&#8217;s constructing your binary file. (Thanks to <a href="http://www.noodlesoft.com/">Paul Kim</a> for reminding me of this functionality). What this means in practice is adding arguments like this to your Xcode target&#8217;s &#8220;Other Linker Flags&#8221; build setting:</p>
<pre>-sectcreate __TEXT __info_plist $(INFOPLIST_FILE)
</pre>
<p>This instructs the linker to crete a new text segment named &#8220;__info_plist&#8221; in the resulting binary, and to fill it with the contents of the referenced Info.plist file. To make sure the INFOPLIST_FILE expands correctly, just make sure you set it in the separate build setting for identifying the Info.plist (the one you&#8217;d normally use in an app, and that is just ignored by default for a command-line tool target).</p>
<p>I brushed up on all this information because I wanted to help ensure that some recent work I did to create a <a href="https://github.com/danielpunkass/peg-multimarkdown">standalone MultiMarkdown tool</a> would be backward compatible with older systems. This required <a href="https://github.com/danielpunkass/peg-multimarkdown/commit/ca523bac1fb03b9cfdcf540805e677086c063704">adding an embedded plist</a> much as I&#8217;m describing here.</p>
<p>(<strong>Note:</strong> I have gotten some feedback to the effect that the __info_plist segment&#8217;s minimum system version requirements may not actually be consulted properly on Mac OS X 10.5. This would be a bummer, and in fact sort of reject the whole point of embedding the Info.plist in this case. I&#8217;m going to see if I can confirm whether it doesn&#8217;t in fact work.)</p>
<p>You could technically embed all kinds of stuff in the binary, with different section names. But the contract in this case is that when Mac OS X is determining information about an executable, it will consult <strong>the bundle&#8217;s Info.plist file</strong>, if it happens to be an executable in a bundle, or <em>the binary&#8217;s __info_plist segment</em>, if it happens to have one.</p>
<p>Another common reason for needing to embed Info.plist information into a standalone binary is if you are using Apple&#8217;s code signing mechanism to sign an individual binary tool. Code signing uses information from the Info.plist of a product, and in the case of standalone binaries, the only product-cohesive place to put this is in the binary itself.</p>
<h3>Examining Binary Info.plists</h3>
<p>After you&#8217;ve performed the magic above, you&#8217;ll probably be keen to inspect your command-line tool&#8217;s Info.plist to see if it worked. To do this, you can use the otool command from the Finder. If you run otool with the &#8220;-l&#8221; option to show all load commands, it will include the load command that identifies the __info_plist segment. Use grep to narrow it down to the part you&#8217;re interested in:</p>
<pre>otool -l ./yourTool | grep info_plist -B1 -A10
</pre>
<p>Any results at will confirm that there is Info.plist information in the binary, but how does it look? The &#8220;-s&#8221; option to otool lets you examine the contents of a specific segment in a binary, but it dumps it out as hex code. Fortunately, another system-bundled tool called &#8220;xxd&#8221; is capable of easily converting between hex-dump and text formats. As it turns out, some of Apple&#8217;s bundled developer tools (at least on my Mac) contain these embedded __info_plist sections, so if you don&#8217;t have a command line tool of your own to try this on, you can peek at what the &#8220;atos&#8221; tool has to say for itself:</p>
<pre>otool -s __TEXT __info_plist /usr/bin/atos | xxd -r
</pre>
<h3>In Summary</h3>
<p>Info.plist values are important for conveying information about your product, from the crudest, most obvious stuff like version number, to the most nuanced details such as which architectures are supported. Knowing how to specify an application or tool&#8217;s requirements as precisely as possible will ensure that the product performs optimally on whatever supported system your user happens to be using. I&#8217;ve barely scratched the surface here with a few common deployment keys that control execution behavior on Mac OS X. Be sure to skim Apple&#8217;s <a href="http://developer.apple.com/library/mac/#documentation/General/Reference/InfoPlistKeyReference/Introduction/Introduction.html">Information Property List Key Reference</a> to see if there are other useful bits of information you can share for your application <em>or for your command-line tool.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/2083/the-power-of-plist/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Safari Keychain Woes</title>
		<link>http://www.red-sweater.com/blog/2039/safari-keychain-woes</link>
		<comments>http://www.red-sweater.com/blog/2039/safari-keychain-woes#comments</comments>
		<pubDate>Fri, 29 Jul 2011 20:57:24 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Lion]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=2039</guid>
		<description><![CDATA[I&#8217;ve been running OS X Lion for a long time and generally enjoying it. But at some point along the line, Safari 5.1 stopped correctly inserting my keychain passwords into forms for me. For the longest time, I assumed it was simple mistakes: I had neglected to ever approve &#8220;remember this password,&#8221; or I had [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been running OS X Lion for a long time and generally enjoying it. But at some point along the line, Safari 5.1 stopped correctly inserting my keychain passwords into forms for me.</p>
<p>For the longest time, I assumed it was simple mistakes: I had neglected to ever approve &#8220;remember this password,&#8221; or I had somehow invalidated the password in my keychain. But recently I have come to realize that Safari is no longer auto-filling passwords for me on any site. Ever. This sucks. Usually when something like this happens, the first thing I do is &#8220;Repair Keychain&#8221; from the Keychain Access application. But in this case, the keychain is reportedly not damaged. No help.</p>
<p>To research this problem, I started the way I usually do: Googling it. While there are <a href="http://www.google.com/search?client=safari&amp;rls=en&amp;q=safari+keychain+lion&amp;ie=UTF-8&amp;oe=UTF-8">many promising search results</a>, most of them lead to &#8220;solutions&#8221; that are not applicable to my scenario. Most commonly it seems the user has somehow ended up with the appropriate &#8220;User names and passwords&#8221; checkbox being turned off in Safari&#8217;s AutoFill preferences.</p>
<p>So how does a programmer like myself approach a problem like this? In recent years, Apple&#8217;s Instruments application has become an incredible asset for tracking down weird behavior not only in my own apps, but in other apps and in the system itself. I opened it up and started a new &#8220;Time Profiler&#8221; instrumentation session, targeting Safari. I know that Safari <em>used to</em> autofill my password whenever I typed in an account name that it recognized, so I start Instruments &#8220;sampling&#8221; Safari while I type my PayPal account name into the PayPal login page, and stop it after I&#8217;m done.</p>
<p>I want to figure out where Safari is failing to get my password, so I take a wild leap and assume the corresponding function call in Safari contains the word &#8220;password.&#8221; Typing this into the Instruments search box yields promising results:</p>
<p><img title="Instruments.png" src="http://www.red-sweater.com/blog/wp-content/downloads/2011/07/Instruments.png" border="0" alt="Instruments" width="448" height="103" /></p>
<p>Now I know that Safari is at least <em>making an effort</em> to fetch the corresponding password for me. I see that it&#8217;s calling -[NSURLCredential password], which in turn calls a lower-level Keychain Services function, SecItemCopyMatching(). But why isn&#8217;t it filling in my password?</p>
<p>At this point I switch to gdb, where i can attach to the running instance of Safari and dig a little deeper into the issue.</p>
<pre>% gdb
(gdb) attach Safari
(gdb) b -[NSURLCredential password]
Breakpoint 1 at 0x7fff8ddff4af
(gdb) c
Continuing.
</pre>
<p>I know from Instruments that Safari will call this method when it tries to autofill my password, so I go back to Safari and enter my PayPal ID again. Sure enough, Safari &#8220;freezes&#8221; indicating that gdb has interrupted it where my breakpoint was set. Now, I realize this isn&#8217;t for the faint of heart, but you can use gdb to effectively debug an application, even if you don&#8217;t have the source code. You just have to know a bit about how Apple&#8217;s compiler translates source code into corresponding assembly language instructions, and where the <a href="http://www.clarkcox.com/blog/2009/02/04/inspecting-obj-c-parameters-in-gdb/">arguments are placed</a> when calling methods.</p>
<pre>Breakpoint 1, 0x00007fff8ddff4af in
-[NSURLCredential password] ()
(gdb) d
Delete all breakpoints? (y or n) y
(gdb) po $rdi
&lt;NSURLCredential: 0x7ffd34d62920&gt;: paypal@jalkut.com
(gdb) po [$rdi password]
2: x/i $pc  0x7fff9192760e &lt;gdb_class_getClass+4&gt;:
	mov    0x20(%rdi),%rax
Can't print the description of a NIL object.
(gdb)
(gdb) p (int) [$rdi hasPassword]
$11 = 1
</pre>
<p>What I&#8217;ve done here is first delete the breakpoint, so I don&#8217;t get interrupted while poking around from gdb itself. Then, I display the NSURLCredential object&#8217;s description, confirming it corresponds to the account I&#8217;m trying to log into. Finally, I call the password method on this NSURLCredential object myself, so I can see quickly and easily what the response will be. Gdb&#8217;s objection to trying to print a NIL object confirms that <em>the password is not being returned.</em> I am further able to confirm with NSURLCredential&#8217;s &#8220;hasPassword&#8221; method that the keychain <em>does have a password for this account</em>, but it isn&#8217;t being returned.</p>
<p>Here we have a situation where apparently Safari is trying to get my password, but the system is vexing it. Let&#8217;s confirm by setting a breakpoint a little deeper, at the Keychain Services level that we also noticed in Instruments.</p>
<pre>(gdb) b SecItemCopyMatching
Breakpoint 3 at 0x7fff85919582
(gdb) c
Continuing.

Breakpoint 3, 0x00007fff85919582 in SecItemCopyMatching ()
(gdb) po $rdi
{
    acct = "paypal@jalkut.com";
    atyp = form;
    cdat = "2007-06-02 16:17:01 +0000";
    class = inet;
    desc = "Web form password";
    icmt = default;
    labl = "www.paypal.com (paypal@jalkut.com)";
    "m_Limit" = "m_LimitOne";
    mdat = "2011-07-29 15:30:15 +0000";
    port = 0;
    ptcl = htps;
    "r_Data" = 1;
    srvr = "www.paypal.com";
}
</pre>
<p>So far, so good. It looks like NSURLCredential is properly passing a set of criteria to the keychain, describing the kind of password item it&#8217;s looking for. I take a peek at the second argument to SecItemCopyMatching, which is a pointer to where the result will be stored, and then I ask gdb to continue executing until the function is complete.</p>
<pre>(gdb) x/x $rsi
0x7fff62eb3590:	0x0000000000000000
(gdb) fin
Run till exit from #0  0x00007fff85919582 in SecItemCopyMatching ()
0x00007fff86417c29 in URLCredentialInternetPassword::copyPassword ()
</pre>
<p>When gdb returns control to me, I know the function has finished calling, so I examine the result area in memory.</p>
<pre>(gdb) x/x 0x7fff62eb3590
0x7fff62eb3590:	0x0000000000000000
</pre>
<p>Indeed, it&#8217;s NULL! What is going on, here? I decided to dust off my <a href="http://www.red-sweater.com/blog/170/usable-keychain-scripting">Usable Keychain Scripting</a> tool, which makes it easy to use AppleScript to search and inspect the keychain. Is the inability to access the password a system-wide thing, or just something that is vexing Safari?</p>
<pre>tell application "Usable Keychain Scripting"
	tell current keychain
		password of keychain item "www.paypal.com (paypal@jalkut.com)"
	end tell
end tell
</pre>
<p>The script works perfectly, first causing the system to ask permission to authorize &#8220;Usable Keychain Scripting&#8221; to access the keychain item, and then returning the expected password string. This got me thinking, is it possible I&#8217;ve somehow got Keychain Accessing refuse access only to Safari?</p>
<p>When I look at the &#8220;Access Controls&#8221; for the affected keychain item, it lists Safari as one of the permitted apps. What the hell, I think. I&#8217;ll remove it from the list, and then re-add it. To try to &#8220;dislodge&#8221; something. Confoundingly, everytime I try to add it, it just silently fails to appear in the list. I am able to add any other app without an issue.</p>
<p><img title="AuthorizedApps.png" src="http://www.red-sweater.com/blog/wp-content/downloads/2011/07/AuthorizedApps.png" border="0" alt="AuthorizedApps" width="454" height="330" /></p>
<p>As a quick check, I change the setting to &#8220;Allow all applications to access this item,&#8221; and save the changes. When I return to Safari and type in the login name, it instantly fills in the password for me.</p>
<p>My system has a functional keychain but Safari seems unable to be authorized to access it, either on a one-time basis or as a &#8220;always allow&#8221; permission. I finally got the clever idea to look at /var/log/secure.log, which frankly, I should have done about 5 hours earlier. What&#8217;s this?</p>
<pre>com.apple.SecurityServer[33]: suppressing keychain prompt
for invalidly signed client /Applications/Safari.app(2938)
</pre>
<p>Aha! So that would explain it. Funny, I don&#8217;t <em>remember</em> tweaking anything inside the Safari application bundle, but this is certainly a very real example of how a broken code signature on Mac OS X can cause extremely subtle, hard to track-down &#8220;bugs.&#8221; I re-signed the applicaton on my own:</p>
<pre>codesign -f -s - /Applications/Safari.app
</pre>
<p>When I reopened the app, and went to PayPal&#8217;s site, voila! It prompted me for permission, I approved, and now everything is back to normal.</p>
<p>I examined the Safari.app bundle contents to try to remember what I might have tweaked. Then my memory was jogged. I had opened and edited Safari&#8217;s Info.plist file to play around with some settings. Don&#8217;t ask, it&#8217;s an even longer story than this.</p>
<p>I take full responsibility for getting myself into this mess. I&#8217;ll certainly be more careful in the future to consider the implications of breaking code signatures on apps. However, I do think that the failure behavior could have been more informative. That NSLog I found in the console about refusing to prompt the user because of a broken code signature, could have been presented as a dialog that would instantly inform the user something is fishy. If my copy of Safari <em>actually had been compromised</em> by a nefarious individual, I wouldn&#8217;t have thought twice about continuing to enter my passwords and trying my damnedest to get Keychain to share my passwords with the compromised application.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/2039/safari-keychain-woes/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>MarsEdit 3.1.4</title>
		<link>http://www.red-sweater.com/blog/1531/marsedit-3-1-4</link>
		<comments>http://www.red-sweater.com/blog/1531/marsedit-3-1-4#comments</comments>
		<pubDate>Tue, 30 Nov 2010 15:41:49 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Debugging]]></category>
		<category><![CDATA[MarsEdit]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=1531</guid>
		<description><![CDATA[Relatively hot-on-the-heels of the previous release, MarsEdit 3.1.4, fixes some major memory performance issues and includes some fixes that streamline integration between Tumblr photo posts and the media manager. Major Memory Meltdown I have always been pretty proud of my ability to manage memory usage in my code. In addition to using good programming habits, [...]]]></description>
			<content:encoded><![CDATA[<p>Relatively hot-on-the-heels of the previous release, <a href="http://www.red-sweater.com/marsedit/">MarsEdit 3.1.4</a>, fixes some major memory performance issues and includes some fixes that streamline integration between Tumblr photo posts and the media manager.</p>
<h3>Major Memory Meltdown</h3>
<p>I have always been pretty proud of my ability to manage memory usage in my code. In addition to using good programming habits, I periodically run Apple&#8217;s memory leak-detection tools, and the clang static analyzer. These tools do a <em>great job</em> of finding accidental memory management errors. But as I discovered, they are not enough.</p>
<p>For months I have received anecdotal feedback that MarsEdit is using more RAM than it should. But I couldn&#8217;t find any evidence of wrong-doing on my part, so I committed a major mistake: <em>I just assumed it was normal.</em> MarsEdit uses a lot of Apple&#8217;s frameworks, including WebKit, which is so big and expansive, I assumed there was something about the degree of WebKit I use in MarsEdit that explained the large amount of memory consumption.</p>
<p>Wrong! I was inspired by a recent one-two punch of feedback, combined with a recent blog post I had read, to dig deeper.</p>
<p>Twitter user <a href="http://twitter.com/Fletcher_Chris">@Fletcher_Chris</a> was exceedingly polite when he asked if MarsEdit&#8217;s 200+ MB memory usage was &#8220;normal.&#8221; Ugh! Normal? I don&#8217;t know? I think so? Not knowing about why your software does what it does is a major alarm bell.</p>
<p>Then my friend <a href="http://daringfireball.net/">John Gruber</a> wrote to let me know that not only is he noticing major RAM consumption, but that it&#8217;s something that has bothered him for some time now. A recurring, nagging issue, noticed by somebody who is technically competent enough to know a real issue from a false one. I have a problem on my hands.</p>
<p>It was lucky timing that my friend <a href="http://twitter.com/#!/bbum">Bill Bumgarner</a> recently published an article on the very subject of <a href="http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/">hard-to diagnose memory leaks</a>. I had actually read this article, enjoyed it, and blithely assumed it didn&#8217;t apply to any of my current software challenges.</p>
<p>It turns out that MarsEdit was in fact suffering from exactly this kind of leak: one that the brilliant leak-targeting tools from Apple are not able to detect. For a variety of reasons mainly involving retain cycles, I was neglecting to clean up after a major part of the MarsEdit post editor&#8217;s user interface, which means that every newly created and closed document would leak hundreds of KB of RAM.</p>
<p>Mea fricken culpa. Fixed in 3.1.4.</p>
<h3>Tumblr Photo Posts</h3>
<p><a href="http://www.tumblr.com/">Tumblr</a> has been a major challenge for MarsEdit because of the degree to which it doesn&#8217;t follow the usual paradigm for media management. This means in a nutshell that things you can do with almost every other blog system are not possible in Tumblr, making the user-interface a little clunkier to handle. In particular:</p>
<ol>
<li>Tumblr does not allow direct file uploads. Even though their web-based UI allows you to upload an image for direct insertion into a post, this is not something they have exposed for remote clients such as MarsEdit.</li>
<li>Tumblr supports the notion of a &#8220;Photo&#8221; type of post, but it takes at-most one single photo. Usually MarsEdit is happy to add as many photos as you like to a post, but with Tumblr it has to be limited to one, and requires that the post type be switched to photo.</li>
</ol>
<p>In MarsEdit 3.1.4, I take baby steps towards improving the situation when users do want to publish photos to a Tumblr blog. First, the per-blog &#8220;image constraints&#8221; settings are now applied to Photo posts on a Tumblr blog. So if you&#8217;ve got it set to limit posts to no more the 400&#215;400 pixels, it will apply to any photo you drag in to Tumblr&#8217;s photo well.</p>
<p>I also streamlined the experience when choosing a photo from the Media Manager for a Tumblr-style post. Not only will the image constraints selected in the Media Manager be applied to the photo, but for example selecting and inserting a photo will automatically set the photo for the open Tumblr post document, or create a new post if one is not already open. This should make the photo-blogging experience on Tumblr a lot smoother.</p>
<h3>A Curious Lack of Crash Reports</h3>
<p>Since MarsEdit 3.0 was released, I have included a crash reporter mechanism that will automatically notice when MarsEdit quits for any unexpected reason, and offer to let the user send me a crash log plus any additional information they choose. This has been a great tool for measuring the number of harder-to-find bugs that remain in MarsEdit, and for zeroing in on and fixing some of them.</p>
<p>Luckily, the flow of crash reports is a relative trickle, compared to the number of users running MarsEdit on a daily basis. But after MarsEdit 3.1.3, the crash reports all but dried up! Was I really so brilliant as to accidentally fix any remaining bugs in the application? 3.1.3 forever! </p>
<p>No, what actually happened was I was brilliant enough to <em>break the crash reporter</em> in 3.1.3, so that it would fail to present the dialog to users offering to send in the report. Crashes were still happening, I&#8217;m sure, but I wasn&#8217;t hearing about them. Now fixed in 3.1.4, and I&#8217;m anxious to get back to monitoring the pulse of MarsEdit stability with this great feature.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/1531/marsedit-3-1-4/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Hold On A Minute</title>
		<link>http://www.red-sweater.com/blog/1397/hold-on-a-minute</link>
		<comments>http://www.red-sweater.com/blog/1397/hold-on-a-minute#comments</comments>
		<pubDate>Thu, 09 Sep 2010 18:00:18 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Macintosh]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=1397</guid>
		<description><![CDATA[One of the big new features in MarsEdit 3 is a revamped media manager that allows you to easily browse local libraries from iPhoto, Aperture, etc. This functionality is based largely on the great work of the iMedia project, which was spearheaded by Karelia to replicate Apple&#8217;s own ubiquitous media browsing interface, some variant of [...]]]></description>
			<content:encoded><![CDATA[<p>One of the big new features in <a href="http://www.red-sweater.com/marsedit/">MarsEdit 3</a> is a revamped media manager that allows you to easily browse local libraries from iPhoto, Aperture, etc.</p>
<p><img src="http://www.red-sweater.com/blog/wp-content/downloads/2010/09/Media-Manager.png" alt="Media Manager.png" border="0" width="450" height="371" /></p>
<p>This functionality is based largely on the great work of the <a href="http://code.google.com/p/imedia/">iMedia</a> project, which was spearheaded by <a href="http://www.karelia.com/">Karelia</a> to replicate Apple&#8217;s own ubiquitous media browsing interface, some variant of which is available in Pages, iWeb, Mail, etc.</p>
<p>iMedia has been around for a while, but in the past year or more it has been undergoing a significant overhaul as its primary developers gear up to release the official 2.0 milestone. I have been involved in the 2.0 project for a long time now as an &#8220;early adopter,&#8221; using MarsEdit as a testing ground during the beta phase, and taking (mostly!) only the refined and polished aspects of the product for the final MarsEdit 3.0 release.</p>
<p>We are still ironing out some of the kinks, especially in parts of the project that were not tested in MarsEdit. One of the cool new features is support for the Flickr photo-sharing service. Like MarsEdit&#8217;s own Flickr-browser, it shows thumbnails of images on Flickr, and lets you treat them more-or-less like ordinary image files that you&#8217;d find on your computer.</p>
<p><img src="http://www.red-sweater.com/blog/wp-content/downloads/2010/09/iMedia2.png" alt="iMedia Flickr Support" border="0" width="450" height="344" /></p>
<p>Things get a little bit complicated when a user selects and drags one of these Flickr image thumbnails to another app, such as the Finder, or Photoshop. Since the image lives in the internet, and not on the local hard disk, it is not something that can be popped over to the application in an instant. Instead, a progress dialog comes up while the image is downloaded to the disk, and then the local copy is passed to the receiving application.</p>
<p><img src="http://www.red-sweater.com/blog/wp-content/downloads/2010/09/iMediaFlickr.png" alt="iMedia Flickr Download Panel" border="0" width="400" height="188" /></p>
<p>I try to contribute back when possible in the form of bug fixes and architectural feedback. Some of the work I did for iMedia 2.0 involved updating its drag-and-drop functionality to take advantage of new features in Mac OS X 10.6. In the process, I became a sort of de facto expert on handling dragging, which is a shame, because we could sure use a <em>real</em> expert, instead!</p>
<p>The other day, an issue came up that relates to the dragging of Flickr files. If the download is taking a while, and the user tries to cancel, mouse clicks are apparently ignored and they are stuck with the progress dialog above. I agreed to look into the issue, but there was just one problem: my network is too fast! Whenever <em>I</em> try to drag a Flickr image to another app, it&#8217;s done within a couple seconds, and I don&#8217;t have time to play around with clicking the cancel button.</p>
<p>If only I could get a <em>really slow connection</em> to Flickr, then I could easily test this. In the old days of Mac OS 9 or earlier, I may have resorted to plugging in a slow modem to simulate the experience of the less bandwidth-fortunate. In Mac OS X however, I can take advantage of the advanced firewall software that comes bundled with the operating system, and which allows me to configure &#8220;traffic shaping&#8221; policies on the traffic coming in and out of my computer. I found a great <a href="http://hints.macworld.com/article.php?story=20080119112509736">hint from Macworld</a> that got me on the right track.</p>
<p>My goal is to cause Flickr downloads to be artificially slow. In order to achieve this goal I need to find the specific web address that the downloads come from. To do this, I use the standard tcpdump terminal utility, which also comes bundled with Mac OS X:</p>
<pre>
sudo tcpdump -Atqp -s 0 -ien1
</pre>
<p>The only part you may want to change is the bit at the end that says &#8220;en1&#8243;. Depending on the network interface you&#8217;re using, you might want en0 or en2 instead. With this running in the terminal, I go back to iMedia and start downloading Flickr files. This lets me see what the addresses of those files look like, and I discover the pertinent host name is &#8220;farm5.static.flickr.com&#8221;. Using the information I gleaned from the Macworld article, I set up the following firewall traffic shaping rules:</p>
<pre>
sudo ipfw pipe 1 config bw 15KByte/s
sudo ipfw add 1 pipe 1 src-port 80 src-ip farm5.static.flickr.com
</pre>
<p>Translation?</p>
<ol>
<li>Create a pipe (you might prefer to call it a &#8220;tube&#8221;). A pipe is an artificial pass-through which can be configured to slow down, block, or otherwise alter the network traffic that goes through it.</li>
<li>Configure the pipe to limit bandwidth to a crawling 15KByte/s.</li>
<li>Configure all traffic coming from port 80 (the standard HTTP port), and originating from a specific hostname at Flickr, to pass through that pipe.</li>
</ol>
<p>As soon as these commands are executed, the pipe is in place, and Flickr download speeds are brought to screeching halt. I can now debug the issue with the download dialog and the cancel button patiently and curiously, instead of racing to try clicking the button while I still have the chance.</p>
<p>When I&#8217;m done debugging, I definitely want to delete the pipe, so that download speeds go back to normal:</p>
<pre>
sudo ipfw delete 1
</pre>
<p>Mucking around with the built-in firewall on Mac OS X is not for the extremely faint-of-heart. This is why all the commands listed in this entry require &#8220;sudo&#8221; superuser privileges. Yes, you could seriously screw up your computer&#8217;s network connection if you do something wrong. But if you are the type of person whose work requires you to test and debug network related tasks, this traffic shaping functionality can be a real asset when it comes to mimicking the network environments of other people.</p>
<p><strong>Addendum:</strong> I should have known I might be doing it the hard way, as usual. Clint Ecker <a href="http://twitter.com/clint/status/24032579293">reported on Twitter</a>, and several folks in the comments below, that <a href="http://mschrag.github.com/">speedlimit</a>, a Mac OS X preference pane, gets the job done in a much friendlier manner.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/1397/hold-on-a-minute/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>RegExKitLite v. Clang</title>
		<link>http://www.red-sweater.com/blog/1345/regexkit-clang</link>
		<comments>http://www.red-sweater.com/blog/1345/regexkit-clang#comments</comments>
		<pubDate>Fri, 23 Jul 2010 21:42:21 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=1345</guid>
		<description><![CDATA[I finally updated to Xcode 3.2.3. I was a little late because I had other priorities, but I wanted to get my iPhone projects building and installing onto my iPhone OS 4.0 devices, so I decided to download and install the latest SDK. Unfortunately, this seemingly minor update presented a major failure in my debug [...]]]></description>
			<content:encoded><![CDATA[<p>I finally updated to Xcode 3.2.3. I was a little late because I had other priorities, but I wanted to get my iPhone projects building and installing onto my iPhone OS 4.0 devices, so I decided to download and install the latest SDK.</p>
<p>Unfortunately, this seemingly minor update presented a major failure in my debug builds, which I&#8217;m adventurously compiling using the LLVM clang compiler. They built fine with Xcode 3.2.2, but starting in 3.2.3, I got a linkage failure, tracing back to the popular open source <a href="http://regexkit.sourceforge.net/RegexKitLite/">RegExKitLite</a>:</p>
<pre>
Undefined symbols:
  "___gxx_personality_v0", referenced from:
      _rkl_debugCacheSpinLock in RegexKitLite.o
      ...
  "__ZSt9terminatev", referenced from:
      +[NSString(RegexKitLiteAdditions) clearStringCache]
      in RegexKitLite.o
</pre>
<p>What? Those symbols smack of C++, but there isn&#8217;t any C++ code in my project. At least, I don&#8217;t think there is. RegExKitLite is so famously <em>advanced</em> in its designed, I couldn&#8217;t easily tell you whether there was stuff in there intended as C++ or not. On a whim, I tried to switch the file type to C++ to see if that made clang any happier. No, it screamed bloody murder. It agrees with me, RegExKitLite is <em>not</em> C++ code.</p>
<p>So why the link errors? I examined the compile line carefully for RegExKitLite and confirmed that it&#8217;s using clang in a manner that should only be generating plain C linkage:</p>
<pre>
/Developer/usr/bin/clang -x objective-c -arch x86_64 ...
</pre>
<p>But when I look at the resulting RegExKitLite.o with the &#8220;nm&#8221; command-line tool, it shows the culprits symbols have been listed as references in the binary object file:</p>
<pre>
% nm RegexKitLite.o | grep -e terminate\\\|personality
                 U __ZSt9terminatev
                 U ___gxx_personality_v0
</pre>
<p>Normally when I&#8217;m getting some kind of issue like this, I just type in the problematic symbols in to Google and usually find somebody else has found and solved the problem. No such luck this time. There are lots of false positives for the typical reason somebody runs into this link error: they are compiling legitimate C++ code but neglecting to link with the stdc++ library. But in our case, we are <em>not compiling C++ code</em>, but we&#8217;re ending up with C++ dependencies nonetheless.</p>
<p>I hopped on to the #clang IRC channel on irc.oftc.net, where a couple extremely helpful clang engineers (thanks to dgregor and rjmccall) helped talk me through the problem, and determine that it does seem to be a clang 1.5 bug. They confirmed that with their latest and greatest clang the bug seems to be fixed, but I was curious to confirm it myself, so I <a href="http://clang.llvm.org/get_started.html#build">checked out and built</a> the latest clang, too. Sure enough, all is well for future generations!</p>
<p>But what do we do now, stuck with the clang 1.5 that ships with Xcode? There is a crude workaround: simply link to stdc++. But yuck! All that C++ linkage dirtying up my pristine Objective-C project? Since I only use clang (for now) to build debug builds, I don&#8217;t have too much of a problem doing this. But if I was shipping these binaries I would be very hesitant to make that concession.</p>
<p>Radar #<a href="rdar://problem/8230225">8230225</a>: clang 1.5 forces linkage to C++ for non-C++ source file<br />
(<a href="http://openradar.appspot.com/8230225">Open Radar Link</a>)</p>
<p>The best we can do is report the issue to Apple and let them decide whether it&#8217;s worth their time to backport whatever fix in later clang is missing from clang 1.5. If you have other suggestions for how to work around the problem in the mean time, please do chime in with a comment below.</p>
<p><strong>Update:</strong> The author of RegExKitLite kindly chimed in below with a pointer to the <a href="http://llvm.org/viewvc/llvm-project?view=rev&#038;revision=103938">revision</a> in the clang source repository that that fixes the issue. He also suggests a simple, and seemingly safe workaround, involving a slight tweak to the RegExKitLite source code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/1345/regexkit-clang/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>A Stroke Of Luck</title>
		<link>http://www.red-sweater.com/blog/1150/a-stroke-of-luck</link>
		<comments>http://www.red-sweater.com/blog/1150/a-stroke-of-luck#comments</comments>
		<pubDate>Fri, 09 Apr 2010 18:28:38 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Macintosh]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=1150</guid>
		<description><![CDATA[One of my customers reported a really subtle bug having to do with a keyboard shortcut for a command. I&#8217;m going to change some facts to protect the innocent, but imagine I got a report: &#8220;Every time I press cmd-N to create a new document and start typing, instead of accepting the text, it just [...]]]></description>
			<content:encoded><![CDATA[<p>One of my customers reported a really subtle bug having to do with a keyboard shortcut for a command. I&#8217;m going to change some facts to protect the innocent, but imagine I got a report:</p>
<blockquote>
<p>&#8220;Every time I press cmd-N to create a new document and start typing, instead of accepting the text, it just beeps at me.&#8221;</p>
</blockquote>
<p>This seems impossible to me. Creating a new document and typing into it is fundamental to my product. Surely if it was broken I would know from my own daily testing of the application. I try diligently to reproduce it, but of course, I can&#8217;t. Create a new document. Start typing. Everything works, everybody&#8217;s happy. Except the person who reported the bug.</p>
<p>At some point in my tinkering I stumble upon the bug. Beep. I can&#8217;t type. There it is! What a drag. <em>This application sucks!</em></p>
<p>Now that I&#8217;ve seen and heard the bug with my own eyes, I&#8217;m more committed than ever to fixing it. But how on earth did I do it? I try several more times and am unable to reproduce the problem.</p>
<p>I have only spotted the issue once in my dozens of trials, yet the customer claims it affects him <em>every single time.</em> ﻿What explains this? Maybe it simply doesn&#8217;t happen as often on my Mac as it does on his. My thoughts turn to the brute force of AppleScript. If this happens only once in a blue moon on my Mac, surely I can reproduce it by running a script that iterates the test conditions hundreds or thousands of times. I open AppleScript Editor and enter the following:</p>
<p><pre>
tell application "System Events"
	repeat 100 times
		keystroke "n" using command down
		keystroke "Testing typing"
	end repeat
end tell</pre>
</p>
<p>
Nothing! Even after running it 1000 times, nothing. How can this be? How could something so common for the customer, something that I saw myself <em>once</em>, be so difficult to reproduce on my Mac?
</p>
<p>
After playing around a bit more, I started to reproduce it more readily. What was happening? I couldn&#8217;t figure it out, but something &#8220;felt&#8221; a little different when I reproduced it. I thought carefully about the parameters of the bug, as exemplified (I thought) by my script:
</p>
<ol>
<li>The command key is pressed.</li>
<li>The N key is pressed.</li>
<li>The N key is released.</li>
<li>The command key is released.</li>
<li>Typing into the new document is attempted.</li>
</ol>
<p>
I looked again at the script. Perhaps this &#8220;keystroke&#8221; command is not literal enough. For all I know it&#8217;s circumventing the normal key events that get generated when you type on the keyboard. On a lark, I modified the script to be more explicit:
</p>
<p><pre>
tell application "System Events"
	repeat 100 times
		key down {command}
		key down  "n"
		key up "n"
		key up {command}
		key down "x"
		key up "x"
	end repeat
end tell</pre>
</p>
<p>
Here we have a more literal match with my analysis of what happens. Hold down the command key, press the N key, release, then type something. In this case I just type an x character because I figure any typing is enough to trigger the bug.
</p>
<p>
I ran this 100 times as well and no luck. The bug is simply not reproducible through scripting. I guess I&#8217;ll have to figure out what conditions are making it more likely for the customer to run into the bug. Maybe he has some 3rd party software that is interfering. Or &#8230; wait a minute.
</p>
<p><pre>
tell application "System Events"
	repeat 100 times
		key down {command}
		key down  "n"
		key up {command}
		key up "n"
		key down "x"
		key up "x"
	end repeat
end tell</pre>
</p>
<p>
I ran the modified script and the bug immediately exhibited itself. So what changed? Look carefully and you&#8217;ll see that my previous script assumed that when a keyboard shortcut is pressed, there is a sort of nested symmetry to the order of pressing and releasing the keys. When I press keyboard shortcuts, I hold the modifier keys down throughout the stroke, and release only after the letter key has been released. But this customer has muscle memory that inclines him to instead release the keys in the order they were pressed. When he releases the N key, the command key has &#8220;long&#8221; since been released. </p>
<p>
This subtle difference turns out to trigger a bug in my event monitoring code that, to make a long story short, robs first responder status from the default view in the document. So when he creates a new document, there is no first responder, and his typing just causes a bunch of beeps. When I create a new document, there&#8217;s always a first responder, so I don&#8217;t see the bug.
</p>
<p>
As difficult as this bug was to track down, it would have been near impossible without the theory testing, disproving, and ultimately proving tool of using AppleScript and System Events to zero on in the behavior. Sometimes when the steps a customer provides to reproduce a bug seem <em>exactly the same</em> as what you&#8217;re doing, you&#8217;re just not trying hard enough to find the difference.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/1150/a-stroke-of-luck/feed</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>NSURLConnection Crashing Epidemic</title>
		<link>http://www.red-sweater.com/blog/452/nsurlconnection-crashing-epidemic</link>
		<comments>http://www.red-sweater.com/blog/452/nsurlconnection-crashing-epidemic#comments</comments>
		<pubDate>Thu, 24 Jan 2008 18:54:50 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[applebugfriday]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[MarsEdit]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/452/nsurlconnection-crashing-epidemic</guid>
		<description><![CDATA[I&#8217;m proud to say that all of my apps are pretty solid. They rarely crash. At least, I assume they rarely crash, because I very rarely receive crash reports from users. When I do, it&#8217;s usually from beta testers before the application has been shared with the general public. But after Apple released 10.4.11, I [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m proud to say that all of my apps are pretty solid. They rarely crash. At least, I assume they rarely crash, because I <em>very</em> rarely receive crash reports from users. When I do, it&#8217;s usually from beta testers before the application has been shared with the general public.</p>
<p>
But after Apple released 10.4.11, I started receiving crash reports at an accelerated pace. The log is the same in every instance, and culminates in what appears to be a threaded NSURLConnection caching operation:
</p>
<p><pre>
-[NSURLConnection(NSURLConnectionInternal)
	_didFinishReturnCachedResponse:]
-[NSHTTPURLProtocol startLoading]
-[NSURLConnection(NSURLConnectionInternal)
	_performOriginLoad]
</pre>
</p>
<p>
Now it so happens that WebKit is the one crashing in many of these cases, but I suspect the problem is more widespread than that. In any case, the problem is definitely more widespread than just MarsEdit. Searching Google reveals <a href="http://www.google.com/search?hl=en&#038;safe=off&#038;client=safari&#038;rls=en-us&#038;q=_didFinishReturnCachedResponse+crash&#038;btnG=Search">a number of similar results</a>, from a variety of applications, including Apple&#8217;s own.
</p>
<p>
If you&#8217;re a developer and your application uses WebKit or NSURLConnection, chances are you&#8217;ve noticed an increase in crash reports, too. Always on 10.4.11, always involving NSURLConnection. If you&#8217;re a user running 10.4.11, chances are you&#8217;ve noticed that network-enabled applications seem to be a bit more flakey and crash-prone.
</p>
<p>
The fact that the bug seems to be fixed in Leopard makes me think that this is a bug whose source was identified and fixed. Now the question is, will Apple ever ship a 10.4.12 containing a fix? Or will those users be stuck in crash-ville forever?
</p>
<p>
Apple needs to get this fixed. For these poor 10.4.11 users who got stuck with a buggy URL loader, and for us poor developers who have to gently explain to them that it&#8217;s out of our control. I have to assume there&#8217;s already a bug reported against this, but better safe than sorry, I wrote up another one: Radar #5704773.
</p>
<p>
So why I am I writing this blog entry? Because I want other developers who read my blog or who find it by Google search to know that <em>they&#8217;re not crazy</em>. And I want users who run into this crash to please remember to send the crash report to Apple. They need to know that this is a serious issue that is impacting you and the apps you use.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/452/nsurlconnection-crashing-epidemic/feed</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Cocoa-Java Porting Step 2: Life Support</title>
		<link>http://www.red-sweater.com/blog/281/cocoa-java-porting-step-2-life-support</link>
		<comments>http://www.red-sweater.com/blog/281/cocoa-java-porting-step-2-life-support#comments</comments>
		<pubDate>Tue, 20 Feb 2007 19:04:41 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Intel]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/281/cocoa-java-porting-step-2-life-support</guid>
		<description><![CDATA[In the first part of this series, Triage, I talked about some of the earliest steps I took in the process of purchasing a Cocoa-Java application and porting it to Objective C. In this article, I&#8217;ll discuss some techniques I stumbled upon for working with a legacy Java code base while gradually migrating functionality to [...]]]></description>
			<content:encoded><![CDATA[<p>In the first part of this series, <a href="http://www.red-sweater.com/blog/271/cocoa-java-porting-step-1-triage">Triage</a>, I talked about some of the earliest steps I took in the process of purchasing a Cocoa-Java application and porting it to Objective C. In this article, I&#8217;ll discuss some techniques I stumbled upon for working with a legacy Java code base while gradually migrating functionality to Objective C. In keeping with the medical metaphors, I&#8217;m calling this segment &#8220;Life Support&#8221; because, while the project in this state is by no means dead, it&#8217;s far from healthy.</p>
<p>
What does it mean for a project to be <em>alive</em>? I&#8217;m adopting a definition of life that is roughly &#8220;as freaking close to original functionality as possible.&#8221; That means the application needs to be launchable. It needs to perform its advertised purpose. Ideally, a project in &#8220;life support&#8221; should be less than a week away from &#8220;shippable&#8221; at any time.
</p>
<p>
The bad news? To maintain this standard, you might put up a ton of scaffolding code  today to keep the application alive, only to tear it down in a few days when the complementary structures in another part of the application have been comparably revised. Some would argue that it&#8217;s better to bid farewell to the life of the application, and commit to a dark period of zero functionality while everything is redesigned and/or ported to the desired specification. This would certainly make for less &#8220;throwaway&#8221; code, but an unfamiliar, non-functioning application scares the living daylights out of me.
</p>
<h3>Clean Code In A Strange Land</h3>
<p>
Back to the specific project at hand. You&#8217;ll recall that during triage, I discovered some cool Objective-C hacks that allowed me to fix the heinous crashing bugs on Intel, while leaving essentially the entire Java code base unchanged. This trick relied on a basic truism of the Cocoa-Java runtime: calling methods on Java objects from Objective-C is relatively easy, while calling back to Objective-C from Java is not.
</p>
<p>
To call a Java class method from Objective-C, you look up the class by name, and send it a message that will, by convention, map to an associated Java class method. When the Java class you&#8217;re messaging is in fact a subclass of a Cocoa class, the messaging can feel extremely natural. For instance, assuming you&#8217;ve got a Java-based Preferences Window controller, this is how you might message it to show its window, from an Objective-C based class:
</p>
<p><pre>
<code>
Class theClass = NSClassFromString(@"PrefsController");
NSWindowController* myPrefs = [theClass sharedInstance];
[myPrefs showWindow:self];
</code>
</pre>
</p>
<p>
Going the other direction, from Java to Objective-C, requires compiled-in bridge code. Much of the Cocoa frameworks from around the 10.2 era is represented in the bridge code provided by Apple. Everything else, including any custom Objective-C classes you&#8217;ve written, would require new bridge code to be generated and linked in to your application. This is apparently still possible, using Apple&#8217;s unsupported and poorly documented &#8220;bridget&#8221; tool. Personally I didn&#8217;t want to touch it. The idea here is to eventually get rid of the Java code completely, so I don&#8217;t want to waste a lot of time making it easier for it to stick around.
</p>
<p>
So here&#8217;s my approach: pragmatically move stuff from Java to Objective-C, keeping in mind that everything I move &#8220;up&#8221; must not be depended on by any other Java code. For example, if I move the Preferences controller from Java to Objective-C, then no longer can any Java code say &#8220;PrefsController.sharedInstance().showWindow(this)&#8221;. So deciding how to proceed will require at least some sense of the dependencies between the various Java classes in my project.
</p>
<p>
I was hoping there might be a nifty way of automatically gathering this information from Apple&#8217;s class diagram tool in Xcode, but it turns out not to be as entirely useful as I&#8217;d hoped. I used a combination of its member variable information, combined with some brute-force global text searches, to roughly plot out a list of all classes, and the <em>Java-based classes</em> that they depended upon. For instance my Java-based application delegate depended upon the Java-based document class, which depended on several Java-based model classes. So I can&#8217;t really port the document or model classes to Objective-C, but I can port the delegate, because no other Java code links directly to it.
</p>
<p>
The idea is to look for &#8220;childless nodes&#8221; in the class hierarchy, and decide whether it is pragmatic to port them no or later.  As classes are migrated up from Java to Objective-C, it reduces the amount of Java code in the project, while keeping the application functionally identical to its former self.
</p>
<p><h3>The Objective-Java Chimera</h3>
<p>Obviously things are never quite so simple. In a real project, dependencies between classes never fall into a perfect tree structure where one can simply pluck classes one-by-one from the top of the tree. In some cases, two classes might mutually depend on one another, in which case it would make sense to port both of them to Objective-C in one fell swoop. Or maybe the vast majority of a class is not dependent on Java, but one small component is. It might make sense to port the class with the caveat that things will not be <em>completely</em> functional, for a short period. The application isn&#8217;t dead! It might be wheezing, but it still <em>basically works.</em>
</p>
<p>
I came up with a technique which I found pretty useful, especially for some of the largest classes in the project. What if a class is half dependent on Java, and half not? It would be great to be able to port just the half of the class that can make it to Objective-C, while postponing the rest for later. Using a &#8220;Chimera&#8221; object that is conceptually part Java and part Objective-C, I was able to achieve this monstrous goal.
</p>
<p>
I applied the technique first to a custom NSView subclass, because I observed a slowness in drawing that I guessed might be sped up by minimizing the amount of cross-bridge messaging and structure conversion that going on every time the view was drawn. In any case, I knew I was not confident about applying Shark measurements to a Java class, and would have a much easier time fine-tuing the performance if all drawing was done in Objective-C. The custom view in this case was a major piece of the application, though. It had its hooks into the model code, and other classes had their hooks into it. And it was relatively huge. It made a great candidate for the Chimera technique.
</p>
<p>
The technique depends on Objective-C&#8217;s ability to forward messages a class doesn&#8217;t implement to another class. So for most practical purposes, an Objective-C class can &#8220;wrap&#8221; another class such that clients of the class think all the work is being done by the wrapper. In this case, we want to sneak a <em>new</em> CustomView class in to the runtime, where the nib file will unarchive and automagically contain an instance of our view instead of the old Java one. Then we&#8217;ll fulfill the contract of the old view class, both by implementing our own methods and by dispatching to it when necessary. Simplifying the situation somewhat, converting a Java class to a Chimera class involves the following steps:
</p>
<p><ol>
<li>Rename the Java class to something new. For instance, &#8220;CustomView&#8221; becomes &#8220;JavaCustomView.&#8221;</li>
<li>Create a new Objective-C class, named after the original. In this case, &#8220;CustomView.m&#8221; is our new source file.</li>
<li>Implement message-forwarding methods. These are where the magic happens.</li>
</ol>
<p>
That&#8217;s the skeletal Chimera. Now you can add whatever methods you like in ObjC and they will automatically take precedence over the Java equivalents. You can even rename the Java equivalents if appropriate, and partly implement methods in ObjC. For instance, you could implement &#8220;awakeFromNib&#8221; such that it first called the Java class&#8217;s &#8220;javaAwakeFromNib&#8221; and then proceeded to do whatever Objective-C based setup was appropriate.
</p>
<p>
So which are the &#8220;message-forwarding methods&#8221; that you need to implement? In my experience, it&#8217;s important to implement respondsToSelector:, methodSignatureForSelector:, and forwardInvocation:. In each case, you&#8217;ll want to  dispatch to the underlying Java object, but only when appropriate. To have an instnce of the Java object around, you&#8217;ll need to add code that, at init time and awakeFromNib time, respectively, instantiates and configures the underlying class. You may also need to do some patching up of IBAction connections or whatnot. The fine-tuning will all be very application-specific.
</p>
<p>
The idea for the &#8220;responds to&#8221; and &#8220;method signature&#8221; methods is you want to return the union of your Objective-C class functionality and the Java class functionality. So first ask <em>your</em> superclass to handle the method, and then only if the result is NO or nil, pass-through to the Java class for further inquiry. The forwardInvocation method will only be reached if nothing in your class could handle the method, so you can just blindly pass these through to the Java class, if it will take them.
</p>
<p>
To make this work, you have to manage the dependencies between the two halves of the Chimera. For instance, it might make sense to maintain redundant copies of the IBAction outlet variables, so that both sides of the world have access to &#8220;outside the class&#8221; dependencies. A pitfall is you might end up storing data in one half of the Chimera and not realizing that the other half is still trying to depend on it. I never said this wasn&#8217;t going to be messy, but it gets the job done.
</p>
<p>
Applying this technique essentially opens the doors wide to staging the port. You can carefully port parts to Objective-C while keeping the application alive. You&#8217;ve got a full-fledged Objective-C class to pass around in &#8220;clean land,&#8221; while Java objects continue to operate as necessary on the Java subset of the class.
</p>
<p><h3>A Healthy Outlook</h3>
<p>In the next and final installment of this series, I&#8217;ll talk about the grunt-work of actually going the final mile, and what we gain by getting there. Porting all those Java classes to Objective-C is fairly easy work, but it&#8217;s tedious. I came up with some tricks that might affect your approach in attacking a similar problem. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/281/cocoa-java-porting-step-2-life-support/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Hexy Little Thing</title>
		<link>http://www.red-sweater.com/blog/279/hexy-little-thing</link>
		<comments>http://www.red-sweater.com/blog/279/hexy-little-thing#comments</comments>
		<pubDate>Wed, 14 Feb 2007 18:59:08 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Free Code]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/279/hexy-little-thing</guid>
		<description><![CDATA[I&#8217;m working on an application now that uses a custom document format. Since my code manipulates this format and spits it back out to disk, I find myself frequently examining the resulting documents using Peter Ammon&#8217;s excellent Hex Fiend to examine the resulting files, and make sure the content is still format-compliant. But while I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working on an application now that uses a custom document format. Since my code manipulates this format and spits it back out to disk, I find myself frequently examining the resulting documents using Peter Ammon&#8217;s excellent <a href="http://ridiculousfish.com/hexfiend/">Hex Fiend</a> to examine the resulting files, and make sure the content is still format-compliant.</p>
<p>
But while I&#8217;m debugging the code that actually does the manipulation, I find myself stuck doing stupid stuff like:
</p>
<p><pre>
(gdb) p/x ((char*)[imageData bytes])[14]
$1 = 0x28
</pre>
</p>
<p>
Ugh! That&#8217;s no way to win the software wars. It occurred to me today that what I really want is something like Hex Fiend built right into the debugger. Why shouldn&#8217;t I be able to hex-dump my NSData objects directly from the console? It turns out I wasn&#8217;t alone in this wish, because Dan Wood <a href="http://gigliwood.com/weblog/Cocoa/Better_description_.html">recently published</a> a category on NSData that allows just that.
</p>
<p>
By simply compiling the NSData category into a given application, you give NSData&#8217;s debugging description superpowers. For instance, here&#8217;s me at the gdb console, examining the contents of the favicon.ico response I just received from NSURLConnection:</p>
<pre style="font-size:1em;">
<code>
(gdb) po imageData
NSData 350 bytes:
00 00 01 00 01 00 10 10 10 00 00 00 00 00 28 01 | ..............(.
00 00 16 00 00 00 28 00 00 00 10 00 00 00 20 00 | ......(....... .
00 00 01 00 04 00 00 00 00 00 C0 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF | ................
FF 00 00 00 FF 00 00 00 EF 00 00 00 DE 00 00 00 | ................
CE 00 00 00 BD 00 00 00 AD 00 00 00 9C 00 00 00 | ................
8C 00 00 00 7B 00 00 00 52 00 00 00 42 00 00 00 | ....{...R...B...
29 00 00 00 10 00 00 00 00 00 00 00 00 00 11 11 | )...............
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 | ................
11 11 11 11 11 11 13 31 11 11 12 55 21 11 1B B1 | .......1...U!...
13 D8 7F FF FB 31 1B B1 6F D4 FB 65 9F D2 1B DB | ....1..o..e....
FB 21 84 11 15 F5 1B FF FC 41 12 78 8D D1 1B B1 | .!.......A.x....
3C C1 2D FF FB 51 1B B1 1A D1 5F 71 11 11 1B C5 | < .-..Q...._q....
BF 81 1C C7 58 61 1A FF C6 11 12 BF FF 81 12 54 | ....Xa.........T
11 11 11 13 52 11 11 11 11 11 11 11 11 11 11 11 | ....R...........
11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00       | ..............
Current language:  auto; currently objective-c
(gdb)
</code>
</code></pre>
</p>
<p>
Dan&#8217;s code is pretty much perfect as-is, but I couldn&#8217;t resist tacking on some additional features. His category hardcodes the dumped data to 1024 bytes, but in my case there are times when I&#8217;m interested in seeing more. I added two category methods to the mix:
</p>
<p><pre style="font-size:1em;">
<code>
// startOffset may be negative, indicating offset from end of data
- (NSString *)descriptionFromOffset:(int)startOffset;
- (NSString *)descriptionFromOffset:(int)startOffset
				limitingToByteCount:(unsigned int)maxBytes;
</code>
</pre>
</p>
<p>
Now I can peek at a specific subrange, or expand the default limit of 1024 bytes. I can even peek at the end of a chunk of data, by specifying a negative offset:
</p>
<p><pre style="font-size:1em;">
<code>
(gdb) po [mDocumentData descriptionFromOffset:-11]
NSData 109 bytes (showing bytes 98 through 109):
02 43 41 54 41 54 4F 4E 49 43 00                | .CATATONIC.
(gdb)
</code>
</pre>
</p>
<p>
Wow! This is a pretty huge addition to my debugging and development toolbelt. Many thanks to Dan Wood for providing the ready-made code to speed up my implementation.
</p>
<p>
<a href="http://www.red-sweater.com/blog/downloads/NSData+RSHexDump.zip">NSData+RSHexDump</a> is freely available to you, under an MIT license.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/279/hexy-little-thing/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Cocoa-Java Porting Step 1: Triage</title>
		<link>http://www.red-sweater.com/blog/271/cocoa-java-porting-step-1-triage</link>
		<comments>http://www.red-sweater.com/blog/271/cocoa-java-porting-step-1-triage#comments</comments>
		<pubDate>Thu, 08 Feb 2007 17:12:21 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Intel]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/271/cocoa-java-porting-step-1-triage</guid>
		<description><![CDATA[When I chose to purchase an existing Java-based Cocoa application, I knew I was taking on some risk. Mac OS X still has a technology within it called the Cocoa-Java bridge, which makes it relatively easy for Java classes to participate in the Cocoa runtime, automatically translating objects like arrays and strings to their language-specific [...]]]></description>
			<content:encoded><![CDATA[<p>When I chose to <a href="http://www.red-sweater.com/blog/257/acquisition-roundup">purchase</a> an existing Java-based Cocoa application, I knew I was taking on some risk. Mac OS X still has a technology within it called the Cocoa-Java bridge, which makes it relatively easy for Java classes to participate in the Cocoa runtime, automatically translating objects like arrays and strings to their language-specific counterparts, and allowing for messaging between objects of the two languages. In short, it makes it possible for Java developers to write Cocoa apps just like an Objective-C developer would, only using Java for all of the custom classes in their code.</p>
<p>
Unfortunately, Apple has all but abandoned the technology. The implications for developers are that Cocoa-Java applications cannot easily adopt new APIs, are mysteriously buggy, and are not easily maintained with the latest versions of Xcode. In short, they are a mine-field of opportunities for disappointment and despair.
</p>
<p>
Nonetheless, I decided to buy a Cocoa-Java application, after looking through the existing sources and making best and worst-case scenario predictions. The previous owner had already disclosed some nuanced issues with running on Intel Macs, so I knew there would be <em>some</em> work before I could ship it in good faith. The amount of work would range from &#8220;a few hacks to get it working on Intel as Cocoa-Java&#8221; to &#8220;a complete rewrite in Objective C.&#8221; I planned to port to Objective C eventually, but I hoped to be able to put the product on the market soon with just a few tweaks to make it robust on Intel. Then I could port to Objective C at my leisure while counting all the money.
</p>
<p>
Now that I&#8217;m 95% done with the process of getting the application into shape, I&#8217;m ready to start writing about it. I hope that by explaining the process of evaluating and overcoming obstacles in the process of doing this port, it will establish a reference for others who are stuck doing the same kind of work. I expect there will be many Cocoa-Java parts in the months to come, as support for the legacy technology continues to diminish. Hopefully some of the wisdom I have earned will come in handy for others.
</p>
<p><h3>Evaluate The Source Base</h3>
</p>
<p>
The first thing you&#8217;ll want to do in approaching any port is to look closely at the existing source files. You don&#8217;t need to completely understand what everything does, you just need to see it and take away an impression. At this stage the style and organization of the content should pose as much interest to you as the raw technical functionality. For example, is the object hierarchy conducive to a typical Cocoa design? Is the code well-commented? Does the code exploit language specific features being that will be difficult to replicate in the target language?
</p>
<p>
In my case the code is well-written, well-commented, and since it&#8217;s Cocoa-Java, it already conforms more or less to a conventional Cocoa way of doing things. Lucky me! Nice purchase, Daniel. The only part of the project that doesn&#8217;t directly translate to Objective-C is the notion in Java of a class that &#8220;extends Thread.&#8221; There is no Objective-C class representation of a &#8220;thread,&#8221; so this would obviously take some modest reorganization. But the use of threads was not extensive, so I did not get scard off.
</p>
<p>
It doesn&#8217;t hurt that Java and C are such close siblings, any amount of porting that does need to be done will retain much of its syntactic appearance. In particular, when porting Cocoa-Java to Cocoa-ObjC, probably 80% of the work will fall into two broad categories of concern:</p>
<ol>
<li>Convert syntax().like().this() to [[syntax like] this].</li>
<li>Pay attention to memory management.</li>
</ol>
<p>
The syntax point is a simplification, but really a lot of it could be ported by trained monkeys, or better yet, regular expressions. Anyway, I&#8217;ll talk more about this in a later segment, but suffice to say that the work of straight porting from Java classes to Objective-C classes can be tedious, but is eminently doable.
</p>
<p><h3>Build And Run</h3>
</p>
<p>
Realistically, this step was probably the first thing you did in evaluating the sources. You&#8217;ve got the Xcode project staring right back at you, how can you resist at least trying? The great news is that my product built and run flawlessly, from the minute I unpacked the source archives and installed them on my Mac. The bad news goes back to those aforementioned &#8220;subtle Intel problems.&#8221; Specifically? Crash on print. Crash on window zoom. Ouch.
</p>
<p>
The crashes in either case point to the Cocoa-Java bridge. An infuriatingly cryptic backtrace essentially lets me know that Cocoa-Java was trying to print some log message (perhaps explaining why it was about to crash?) when it bit the dust:</p>
<pre>
<font style="font-size:.8em;">
#0  0x90a53387 in objc_msgSend ()
#1  0xbfffe250 in ?? ()
#2  0x908103a2 in _CFStringAppendFormatAndArgumentsAux ()
#3  0x9080ec8c in _CFStringCreateWithFormatAndArgumentsAux ()
#4  0x925e2a5d in -[NSPlaceholderString initWithFormat:locale:arguments:] ()
#5  0x92604670 in -[NSString initWithFormat:arguments:] ()
#6  0x9672d308 in _BRIDGELog ()
#7  0x9673305d in _BRIDGEMethodImpStructReturn ()
#8  0x93519c6e in -[NSWindow _standardFrame] ()
#9  0x93732d7c in -[NSWindow zoom:] ()
#10 0x9335cd88 in -[NSApplication sendAction:to:from:] ()
#11 0x9335cce1 in -[NSControl sendAction:to:] ()
#12 0x9335ee91 in -[NSCell _sendActionFrom:] ()
#13 0x9335e94c in -[NSButtonCell performClick:] ()
#14 0x97723a6b in Java_com_apple_cocoa_application_NSWindow_performZoom ()
</font>
</pre>
</p>
<p>
Searching the web for help on this failure was pretty fruitless. I downloaded some other applications that I knew to be Cocoa-Java based, and they <em>didn&#8217;t</em> crash on zoom. So what&#8217;s the deal? What is my involvement in this problem.  Through hard work and luck, I narrowed both crashing problems down to a pretty simple thesis:
</p>
<p>
&#8220;Cocoa-Java will crash on Intel if Cocoa asks Java to return an NSRect.&#8221;
</p>
<p>
It might be overstating the case, but those are the two crashing cases in my application. I suspect there is a byte swapping problem or something. If you return an NSRect, you will crash. Sad story, but fixable. The two method calls in question for me are NSWindowController&#8217;s &#8220;windowWillUseStandardFrame:defaultFrame:&#8221; and NSView&#8217;s &#8220;rectForPage:&#8221;.
</p>
<p><h3>Keep It Running</h3>
</p>
<p>
I went to the auto parts store a few months back, around the beginning of autumn. My car had been running hot, and on the verge of overheating all through the summer. I brainstormed with the clerk about what might be wrong, and we finally agreed that it is probably a problem with my thermostat, but could be a problem with the radiator itself. Fine, it&#8217;s settled. I&#8217;ll replace the thermostat first. But even this involves draining the radiator, perhaps removing it, and a lot of other messy stuff. The shop clerk looked outside at the chilling weather and asked me a few pointed questions: &#8220;How old is this car?&#8221; &#8220;Do you drive it a lot?&#8221;, etc. After hearing my responses of &#8220;pretty old,&#8221; and &#8220;not too much,&#8221; he gave his pragmatic verdict: &#8220;It&#8217;s not gonna overheat in <em>wintah</em>, and who knows if it will even run in the spring?&#8221;
</p>
<p>
The point being, it&#8217;s not always the right time to do the right thing. I&#8217;m confident that that my Cocoa-Java NSRect crashes will disappear if I port the application to Objective C. But can I get away with patching the rough spots today? Moreover, won&#8217;t my customers (existing customers of this application) benefit from having the Intel problem solved sooner, rather than later? I decided to attack the problem of crashing NSRect across the bridge.
</p>
<p>
My first thought was to try to gauge exactly why it crashes. If it&#8217;s truly a byte-swapping issue, I could detect the fact that I&#8217;m running on Intel, and perhaps massage the data to suit the bridge. The major downside to an approach like this is you&#8217;re now at the mercy of Apple leaving the bug in place. In the unlikely event that Apple shows the bridge some love, and fixes the crash, where does that leave me? Now I&#8217;m byte-swapping myself into the same crash some ways down the road.
</p>
<p>
The solution I came up with is simple albeit somewhat of a hack. It&#8217;s the duct tape around the muffler, if you will. If you think about the crashing problem with returning an NSRect, an obvious solution would be for Java to <em>not return</em> an NSRect. To work around this problem, I modified the affected Java classes to return NSString instead of NSRect:</p>
<pre>
<font style="font-size:.8em;">
public String javaSafeStandardFrame(theWindow, defaultFrame)
public String javaSafeRectForPage(pageNumber)
</font>
</pre>
</p>
<p>
Now the program doesn&#8217;t crash. Of course, it doesn&#8217;t zoom or print correctly, either. The problem of course is that Cocoa doesn&#8217;t know to call these &#8220;javaSafe&#8221; versions of the methods, and even if it did, it wouldn&#8217;t know to expect a string in return.
</p>
<p>
This is where the hacking comes in to play. The fact that I&#8217;m working with a Cocoa-Java project doesn&#8217;t mean I can&#8217;t <em>also</em> have Objective-C classes in my project. In fact, at runtime the majority of classes in memory are Objective-C, coming from Apple&#8217;s frameworks. What&#8217;s to keep me from selectively implementing some classes of my own to help soothe this problem? Using a custom class and the powerful technique of class posing, I&#8217;m able to effectively patch out standard versions of the above methods, and replace them with code that calls through to Java, gets a string representation of the rect, and converts it to NSRect for the benefit of Cocoa. Since the NSRect is now <em>returned from Objective C</em>, there&#8217;s no more crash. In my main.m source file:</p>
<pre>
<font style="font-size:.8em;">
[RectSafeWindowController poseAsClass:[NSWindowController class]];
</font>
</pre>
</p>
<p>
And in my custom NSWindowController implementation:</p>
<pre>
<font style="font-size:.8em;">
- (NSRect)windowWillUseStandardFrame:(NSWindow *)theWindow defaultFrame:(NSRect)newFrame
{
  // Your java class instead of "JavaController"
  Class myJavaClass = NSClassFromString(@"JavaController")
  if ([self isKindOfClass:myJavaClass])
  {
    NSString* goodRectString = [self javaSafeStandardFrame:theWindow :newFrame];
    return NSRectFromString(goodRectString);
  }
  else if ([super respondsToSelector:@selector(windowWillUseStandardFrame:defaultFrame:)])
  {
    return [super windowWillUseStandardFrame:theWindow defaultFrame:newFrame];
  }
  else
  {
    // Just return the default
    return newFrame;
  }
}
</font>
</pre>
</p>
<p>
A similar approach was used in the NSView override of rectForPage.</p>
<h3>Take Stock</h3>
<p>Now that my application builds and runs without crashing, it&#8217;s time to ship it, right? Possibly, but in this case I chose not to. Although the application has a mature feature set and benefits from years of evolutionary design, it has become a little bit dated in some ways that I grew increasingly uncomfortable with.
</p>
<p>
Now that the application is running crash free, I can breathe a sigh of relief. I <em>could</em> ship this thing, but I choose not to. I want to be prudent about what I change for the &#8220;1.0 relaunch,&#8221; but there are some nuances of the appearance and performance that need tweaking. And to comfortably tweak those things, I&#8217;m going to have to <em>selectively port</em> some of the Java classes to Objective C. But after all that hard work getting the application to &#8220;shippable,&#8221; I want to be careful not to backslide too much. Tune in next time for a detailed look at migrating Java classes to Objective C without disrupting the overall functionality of the application.
</p>
<p>
Continue reading &#8211; <a href="http://www.red-sweater.com/blog/281/cocoa-java-porting-step-2-life-support">Step 2: Life Support</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/271/cocoa-java-porting-step-1-triage/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>

