<?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; applebugfriday</title>
	<atom:link href="http://www.red-sweater.com/blog/category/articles/apple/applebugfriday/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>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>Flex Your HIG</title>
		<link>http://www.red-sweater.com/blog/221/flex-your-hig</link>
		<comments>http://www.red-sweater.com/blog/221/flex-your-hig#comments</comments>
		<pubDate>Fri, 03 Nov 2006 18:01:14 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[applebugfriday]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[FlexTime]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/221/flex-your-hig</guid>
		<description><![CDATA[Some readers pointed out that in announcing FlexTime 1.1, along with its snazzy new interface, I left out some of the most interesting details to programmers. How did I accomplish all of the little things that add up to the new UI? Like everything else in life, you just bite off a little bit at [...]]]></description>
			<content:encoded><![CDATA[<p>Some readers pointed out that in <a href="http://www.red-sweater.com/blog/219/flextime-11">announcing FlexTime 1.1</a>, along with its snazzy new interface, I left out some of the most interesting details to programmers. How did I accomplish all of the little things that add up to the new UI? Like everything else in life, you just bite off a little bit at a time, and hope for the best. And also like everything in life, it seems a lot easier once you&#8217;ve done it. But looking back I can see a lot of discrete obstacles that I had to overcome, and perhaps my path through the wilderness will prove helpful to you. I&#8217;m going to go over the steps that made up the redesign in roughly chronological order, including links to existing open source packages that I used, and also releasing some small contributions of my own for your review.</p>
<p><h3>Inspiration</h3>
<p>Before anything else, you&#8217;ve got to be inspired to change. That might sound fluffy, but it&#8217;s absolutely critical. If you&#8217;re not convinced that your UI needs an overhaul, then you might as well forget it. You can rub sticks together for an eternity, but if you&#8217;re not cold, you&#8217;ll never start a fire. You have got to be dissatisfied with something before you can make it better. For reference, this is what I was becoming increasingly dissatisfied with before embarking on this journey:
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/FlexTime1.0.png"/>
</p>
<p>
I was pretty happy with FlexTime 1.0 when I released it. It did the job. I had never designed toolbar icons before, so I felt pretty good about the matte blue stencils I came up with using <a href="http://www.nodebox.net/">NodeBox</a>. Hey, that <em>was</em> a nice piece of work for a newbie UI designer who is just trying to get something out the door. But it quickly started to grate on me. The interface was not suited to evolution. The inequities between the square corners of the list view and the round corners of the details box made it hard to embed anything more complicated than the few standard controls I have in there now. I was trapped my 1.0 interface, but I couldn&#8217;t figure out what needed to be done to fix it.
</p>
<p>
What followed was basically a month or more of working on anything but the interface. I couldn&#8217;t bear it. I found myself frustrated whenever I looked at it, because I knew something drastic had to change. But what? I worried I might have to scrap the whole thing and start from scratch.
</p>
<p>
Then I was sitting in Chicago at <a href="http://c4.rentzsch.com/">C4</a>, listening to <a href="http://www.daringfireball.net/">John Gruber</a> talk about the &#8220;death of the HIG.&#8221; He brought up <a href="http://inessential.com/">Brent Simmons</a>, using his <a href="http://www.newsgator.com/NGOLProduct.aspx?ProdID=NetNewsWire">NetNewsWire</a> as an example of somebody who had made a big impact by stepping outside the HIG guidelines. What Brent had done was an app that had broken with traditional HIG guidelines by <a href="http://rentzsch.com/macosx/pushingTheEdge">eliminating the margins</a> around the main views in his window. That&#8217;s when it struck me: &#8220;I&#8217;ve got too many margins.&#8221; I immediately envisioned FlexTime with its list view and details pane flush against the left and right edges of the window. That was it. I just realized that was where I&#8217;d start, and left it in my head to sink in. I spent the rest of the weekend on not really thinking about it.
</p>
<p><h3>Losing The Margins</h3>
<p>When I got home, I didn&#8217;t waste much time getting to work on this. I busted open Interface Builder and started moving stuff around. About the only &#8220;gotcha&#8221; with this exercise is getting the UI to look good flush against the edge. A trick I discovered (and recently saw repeated by Brent Simmons on a mailing list) is that many views, table view included, will look best if its border is hidden off the edge of the screen. To accomplish this, you can simply set the x origin of the view to -1. This is a good trick to keep in your back pocket for a variety of finishing touch-ups.
</p>
<p>
I realized quickly that zero-margins on the left and right sides made the text labels and associated whitespace above the respective sections look stupid. Gasp! Could I just take those labels out? But the user will be lost without them! The main instructiveness of those labels was to tell the user that the list on the left was an &#8220;Activity List.&#8221; I discovered that by changing the main column&#8217;s label from &#8220;Name&#8221; to &#8220;Activity Name,&#8221; I could get this point across well enough without using a sledgehammer to drive it home.
</p>
<p><h3>A Touch Of Polish</h3>
<p>I also decided pretty early on that the streamlined look might go well with one of the &#8220;polished metal&#8221; looks from Apple&#8217;s suite of applications. I ended up using <a href="http://mattgemmell.com/source/">PolishedWindow</a>, which masquerades as &#8220;TunesWindow&#8221; on Matt Gemmell&#8217;s web site. He basically put together an NSWindow subclass that draws its background with a bunch of images  to match Apple&#8217;s iTunes-ish windows. This was a real simple change to integrate. If I get time I might try to improve the code by getting it to use computed gradients instead of images. I feel like the code could probably be a bit faster during resizes. But for a quick fix this was a real champ.
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/FlexTimeHIG1.png"/>
</p>
<p>
Well shoot howdy, that looks pretty good. It&#8217;s such an improvement to my eye that I was frankly about ready to call it a day and ship it. But once you start moving, the inertia of change pulls you along until <em>it&#8217;s</em> ready to slow down. You set out to change one thing, and can&#8217;t estimate how many changes you&#8217;ll ultimately end up making. I showed the screenshot to a few friends, and what do you know, they found <em>plenty</em> to complain about. <em>The icons looks out of place. There is no dividing ridge between the content and the top/bottom sections. The selection of the table should be a gradient. What&#8217;s that funny blank column at the end of your table? Pinstripe grey looks wrong in a polished window.</em> The problem with having smart friends is they always have an opinion. You&#8217;ve got to learn to dismiss some feedback as a matter of taste. People feel passionately about Coke and Pepsi, but what do you know, they&#8217;re both successes. But often the things that rankle one person are going to upset a lot of others, too. So I take early feedback seriously. I might argue with a person, if only to make them justify why their suggestion is right. When the feathers have settled, usually it turns out that they were right, and I&#8217;m wrong. So I fix it.
</p>
<p><h3>Pinstripes, Ridges, and Gradients</h3>
</p>
<p>
It&#8217;s hard to see the pinstriping in the above screenshot, but trust me, it&#8217;s there. It&#8217;s not so bad, because it sort of blends visually to a light grey, but it really bothered some friends who saw it as out of place in the polished window. I also decided to add a gradient shine to the table view selection, and some defining &#8220;ridges&#8221; between the main content and the toolbar on top, and bottom section on the bottom.
</p>
<p>
The ridges are probably the most embarrassing of the three solutions, so I&#8217;ll start with them. I don&#8217;t know what the heck I&#8217;m doing. I&#8217;m a frickin&#8217; professional, but I&#8217;m also an amateur. We all are. Professionals are just amateurs who know it&#8217;s not worth faking like you know something you don&#8217;t. In all seriousness, one of the things that makes me a professional is my ability to prioritize &#8220;working code&#8221; over &#8220;correct code.&#8221;  I look at those ridges, as they appear in something like iTunes, and all manner of possible solutions spring to mind. I can rewrite the window subclass to draw the ridges as part of the background. Or I could devise a special &#8220;polished window content box&#8221; that draws the desired outline on the top and bottom edges. But the simplest solution at the time seemed to be popping arbitrarily colored &#8220;divider lines&#8221; into the UI at the appropriate spots.
</p>
<p>
I for one have always taken the &#8220;divider&#8221; for granted. It&#8217;s such a simple UI element. Usually you drag it in from Interface Builder and let it sit there undisturbed for the life of your product. But I want a <em>colored</em> divider line. In fact, I want four of them, positioned just right so they look like fancy iTunes ridges. In Cocoa, it turns out that divider lines are a very special variant of NSBox! Who knew? So I set about subclassing NSBox to provide colored divider lines. <a href="http://www.red-sweater.com/blog/downloads/RSColoredBox.zip">RSColoredBox</a> should really be called RSColoredDivider or something that is more honest about the presumptions the code makes. I don&#8217;t think it will make a very good colored box, per se. I thought it would at first, but it turns out that the way Cocoa and IB plop down &#8220;divider boxes&#8221;, they have boundaries that lie. Divider boxes are of a special variant and are actually much taller or wider than you&#8217;d assume. Anyway, use that code if you want a colored <em>line</em> in your interface. Just drag a divider in from IB, set its custom class to &#8220;RSColoredBox,&#8221; and then call &#8220;setBoxBorderColor&#8221; on the line at awakeFromNib time. Cheap hacks, baby. Take it or leave it.
</p>
<p>
Getting rid of the pinstripes in my NSTabView is also not quite as simple as one might guess. This is one of those moments where you think &#8220;why doesn&#8217;t NSTabView have a backgroundColor attribute?!&#8221; The options for NSBox are that you can have it draw nothing, or draw pinstripes. Tough love.  The cheapest way I could find to work around this deficiency was to subclass NSTabView and take over the drawing mechanism. Instead of drawing pinstripes, which is all the parent class does, I&#8217;ll just fill a rect. Again, this isn&#8217;t a very robust class &#8211; it only works when the tab view is &#8230; tabless. C&#8217;est la vie. <a href="http://www.red-sweater.com/blog/downloads/RSColorBackgroundTabView.zip">RSColorBackgroundTabView</a> is available for your perusal.
</p>
<p>
Finally, the gradient table view. This is one of those things that can be done right, or any of a million varieties of wrong. I was lucky to discover that <a href="http://www.wilshipley.com/blog/">Wil Shipley</a> had written, during his time at Omni, a perfectly reasonable <a href="http://wilshipley.com/blog/2005/07/pimp-my-code-part-3-gradient.html">gradient-highlighting table view</a>. You&#8217;ll need to snag the code from <a href="http://www.omnigroup.com/developer/sourcecode/">OmniAppKit</a>, where it&#8217;s provided with the same license as everything else in that fine package. The things Shipley&#8217;s code does right are that he computes the gradient programatically, and he obeys the user&#8217;s highlight color. These two qualities made the code an easy sell for me.
</p>
<p><h3>Pie In The Sky</h3>
</p>
<p>
The &#8220;empty column&#8221; in the screenshot above corresponds to the animated pie-chart progress that is displayed when a user is running a FlexTime routine. It becomes obvious what it is, as soon as you start running something. But I had to agree with my critics, a blank column header is kind of a cop-out.
</p>
<p>
My first thought was to simply reuse the excellent pie chart cell I use for the table content, which is based on Jon Wight&#8217;s <a href="http://toxicsoftware.com/blog/toxic_progress_indicator/">Toxic Progress Indicator</a>. I allocated one, configured it appropriately, and then &#8220;setHeaderCell:&#8221; on the NSTableColumn. This sorta kinda worked, but there were major drawbacks. First, the drawing of the pie chart at that size revealed aliasing problems that didn&#8217;t really look polished. I&#8217;d have to edit the code to improve the compositing over the background, or something. Second, when you take over responsibility as a header cell, you take over all responsibility. You&#8217;ve got to draw that cute polished background, in addition to the content. Now I&#8217;m sure I could have gotten this all to work, by employing the existing default table header cell to do some of the heavy lifting, or by subclassing it. But I heard a little voice in my head screaming &#8220;overengineering!&#8221; so I took a step back. <a href="http://www.noodlesoft.com/">Paul Kim</a> pointed out that I could simply &#8220;setImage:&#8221; on the existing header cell, and it would draw it for me, nicely composited over the polished background. Why go to the trouble of dynamically generating a pie chart image when one put together in PhotoShop will look just as good and be 100% predictable?
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/AssTable.png"/>
</p>
<p>
The image looks pretty good in the table header, but what&#8217;s that ugly crud on the edge? Why is it that I can&#8217;t spend more than 15 minutes at a computer without finding a bug in <em>somebody else&#8217;s code</em>? It&#8217;s the curse of the tester. I started my career in Quality Assurance and I&#8217;m doomed now to forever discover all the bugs. What&#8217;s going on here? It&#8217;s a bug in NSScrollView, or NSTableView. When a table view suddenly acquires a vertical slider, it causes the existing table headers to scrunch up and make room. In the space formerly occupied by the right-most table header, a special view is inserted called the &#8220;corner view.&#8221; This view is responsible, normally, for just drawing an empty background. After some debugging I discovered that when an NSTableView acquires a scroll bar, the cornerView is made visible, but not asked to redraw. That means whatever was on the screen before it appeared just gets left there. Usually you get lucky, because what was there is blank table header background. Most table headers are left-aligned (only on left-to-right language systems?), and the text rarely reaches the far right edge of the table. Leave it to me to find the exception.
</p>
<p>
When I run into a bug like this, I like to confirm as quickly and definitively as I can that it&#8217;s not my problem. If I take a simple project, like Apple&#8217;s &#8220;OutlineView&#8221; developer example, and cause it to have text that runs up against the right edge, then I see the same bug:
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/AssTable2.png"/><br />
(Radar #<a href="rdar://problem/4818521">4818521</a>)
</p>
<p>
A workaround is to aggressively listen for table column resizes, and force the corner view to redraw itself whenever this happens:
</p>
<p><pre>
- (void)tableViewColumnDidResize:(NSNotification *)notification
{
   // Force the tableview's cornerview to redraw.
   [[oTableView cornerView] setNeedsDisplay:YES];
}
</pre>
</p>
<h3>Clickable Text</h3>
<p>
One of the biggest payoffs of this redesign was that it suddenly made the most ambitious part of my evolving UI a lot more palatable. I heard loud and clear that people were asking for large timer feedback while a routine was running, but I was <a href="http://www.red-sweater.com/blog/210/flextime-11a1">having a hard time</a> integrating it into the FlexTime UI. While the timers are not perfect, I do think they fit in a lot better in the margin-free context of FlexTime 1.1.
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/FlexTimers.png"/>
</p>
<p>
It&#8217;s worth talking a little bit about that custom UI. I wanted to satisfy two major design requirements:</p>
<ol>
<li>The time display should be large and easy to read.</li>
<li>The time display should be easy to configure and disable.</li>
</ol>
<p>
I decided on large clickable displays. The simplicity of changing a configuration by simply clicking it is hard to argue with. Don&#8217;t like what you see? Click it and see if it gets better. I haven&#8217;t had a lot of feedback yet, but I suspect this &#8220;implicit configuration&#8221; is probably much preferable to a preferences panel or something where the options are painfully selected from a list of radio buttons.
</p>
<p>
Now if you&#8217;re like me and tend to stick with standard UI pieces, you&#8217;re probably wondering how I put that little piece of work together. One reasonable approach would be to design a custom NSView subclass and handle all the hit testing and state changes in there. In fact, that&#8217;s probably a smarter way to go about things, but for whatever reason I tended towards the &#8220;design entirely in IB&#8221; path this time around. The &#8220;custom view&#8221; in this case is an elaborate contraption formed out of NSTabViews, bindings, and clickable NSTextFields. When you click an NSTextField, it changes the &#8220;view mode&#8221; for the display, which is a property of the document. An NSTabView contains the three view modes, and is bound by its &#8220;selectedIndex&#8221; binding directly to the viewing mode (conveniently an enum that matches the NSTabView indices). The text fields for the time displays are bound directly to &#8220;time remaining&#8221; or &#8220;time elapsed&#8221; values, which are NSTimeInterval values (double precision seconds). To present the clock-style format I attach a value transormer, RSTimeIntervalToClockStyleFormat, which turns the seconds into a pretty string as shown.
</p>
<p>
If you imitate this approach, you&#8217;ll soon learn that NSTextField is not clickable by default. But it <em>is</em> an NSActionCell. It has these qualities but normally only uses them in an editable context, where the target/action paradigm is applied when the value changes or editing ends. To extend the functionality to mouse clicks, simply subclass NSTextField (mine is RSClickableTextField) and override mouseDown:
</p>
<p><pre>
- (void)mouseDown:(NSEvent *)theEvent
{
   [self sendAction:[[self cell] action] to:[[self cell] target]];
}
</pre>
</p>
<h3>Buttons 2.0</h3>
<p>By this time, things are really starting to look good. My margins are gone. I&#8217;ve got my gradient. My light grey background. My polish. My pie chart header cell. Up to this point people have been screaming about the buttons, but I&#8217;ve been laughing it off. Haha! Maybe for 1.2. I just couldn&#8217;t muster the psychic energy to tackle such a big part of the UI. But the incongruence of those flat buttons was really starting to gnaw at me. I decided to take a stab at improving at least the color, and it quickly turned into a day-long obsession.</p>
<p>
While the original buttons  were entirely built from NodeBox, I decided I needed  to add some lighting effects and anti-aliasing that were simply not feasible in NodeBox. So I started with the NodeBox generated images, but set up a PhotoShop document to apply various manipulations to the images by filter layers, semi-transparent gradients, etc. It was a learning experience, but I&#8217;m pretty happy with the results.
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/FlexTime1.1.png"/>
</p>
<p>
As you can imagine there was a lot of tweaking and testing in this process, and one of the best things to come of it was my decision to build a &#8220;Generate Toolbar Icons&#8221; script. I organized my PhotoShop document in such a way that all of the various toolbar icons are in one document, so to save a particular icon you just hide all the other buttons&#8217; layers. This is cool because all the effects layers and gradients are consistent and can be changed in one place, where you&#8217;ll be sure they apply to all of the buttons.
</p>
<p>
Hiding and showing the layers would be tedious to do by hand, but PhotoShop&#8217;s &#8220;layer set&#8221; concept makes it easy to script. By putting all the toolbar buttons in a layer set called &#8220;Buttons,&#8221; I am able to easily hide all of them:
</p>
<p><pre>
	set buttonSet to layer set "Buttons" of myDoc
	set visible of layers of buttonSet to false
</pre>
</p>
<p>
Then I can iterate through all the layers in that layer set, setting the visibility of the layer to true, exporting a copy of the image, and setting the visibility back to false:
</p>
<p><pre>
repeat with layerIndex from 1 to count of layers of buttonSet
	set thisLayer to layer layerIndex of buttonSet
	set visible of thisLayer to true
	set outputName to outputPathRoot &#038; name of thisLayer &#038; ".png"
	save myDoc in outputName as PNG with copying
	set visible of thisLayer to false
end repeat
</pre>
</p>
<p>If you&#8217;ve used PhotoShop to &#8220;Save As,&#8221; you know how painful it is to constantly go through the options dialogs. AppleScript makes exporting even one image easier, but with my script I can easily regenerate all nine icons and spit them out directly into the appropriate source directory.</p>
<p><h3>Wrapping Up</h3>
<p>The only downer to doing a GUI redesign is that all of your pictorial documentation becomes instantly obsolete. After the relatively fun work of designing the graphics and tweaking the layout, I realized I&#8217;d have to redo all of my Help Book graphics, and the screenshots for download sites and my web page. The lesson I learned from this is that to whatever extent possible, you should keep the &#8220;art&#8221; separate from the notation. For instance in my documentation I include a screenshot with various annotations made upon it:
</p>
<p>
<img src="http://www.red-sweater.com/blog/images/FlexHelpExample.png"/>
</p>
<p>
In 1.0, I foolishly generated this graphic in Pages or something, and saved it as a bitmap image. Dumb, dumb, Daniel. From here on out I&#8217;ll be conscientious about saving with layers and keeping the application UI &#8220;swappable&#8221; with a new graphic, where only minor adjustments might need to be made to the overlays.
</p>
<p>
That&#8217;s the story of how FlexTime got its HIG on. Hope you enjoyed it picked up a few new tricks along the way.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/221/flex-your-hig/feed</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>CoreGraphics Log Jam</title>
		<link>http://www.red-sweater.com/blog/129/coregraphics-log-jam</link>
		<comments>http://www.red-sweater.com/blog/129/coregraphics-log-jam#comments</comments>
		<pubDate>Fri, 05 May 2006 15:16:58 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[applebugfriday]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/129/coregraphics-log-jam</guid>
		<description><![CDATA[It&#8217;s been a while since I&#8217;ve complained about Apple in the context of an actual bug report, so here is a little diversion back into &#8220;Apple Bug Friday&#8221; land. One of the aspects of Mac OS X programming that can really frustrate traditional Mac OS programmers is the lack of error reporting from many APIs. [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since I&#8217;ve complained about Apple in the context of an actual bug report, so here is a little diversion back into &#8220;Apple Bug Friday&#8221; land.</p>
<p>
One of the aspects of Mac OS X programming that can really frustrate traditional Mac OS programmers is the lack of error reporting from many APIs. While traditional Carbon APIs tend to return numeric failure codes when something goes wrong, it&#8217;s not unusual for CoreFoundation and related APIs to simply return NULL. What&#8217;s the developer to do in this case? The usual argument is that NULL is returned only from functions where a more specific error would not help the programmer convey meaningful information to the user. In other words, if it returns NULL when you don&#8217;t expect it to, your computer is either melting down, or you&#8217;ve got some debugging to do. Regardless of the validity of this argument, it can be infuriating to look at code that seems perfectly correct, and be clueless as to why it is failing.
</p>
<p>
I was chatting with <a href="http://www.toxicsoftware.com/">Jonathan Wight</a> when he shared his frustration with the CGBitmapContextCreate function. He was in the midst of debugging just one of these mind-boggling NULL returns. All the parameters looked <em>more or less</em> correct but the function just plain refused to cooperate.
</p>
<p>
I guess I was between builds or something because I got interested in the problem. While Jon took the more efficient path of carefully examining the parameters being passed and comparing their values to the documentation&#8217;s restrictions, I started traipsing through assembly in Xcode. You know, the fun stuff.
</p>
<p>
Of course, Jon found the answer first. It was a problem with the combination of colorspace and alpha parameters. The limitations are well-documented (if a bit overwhelming) in Apple&#8217;s <a href="http://developer.apple.com/qa/qa2001/qa1037.html">Technical Q&#038;A</a>. In this case, Jon was fetching the values directly from a CGImage that had been loaded from disk. Can&#8217;t blame a guy for thinking that maybe a JPG image&#8217;s attributes might be suitable for creating a bitmap context!
</p>
<p>
Even after the bug was resolved, I continued digging into the framework via the debugger. I&#8217;m due for a complete retraining on Intel, but as long as I have my PowerPC machine around, I&#8217;m fairly comfortable zipping through the various API to see what <em>really</em> happens when an error occurs.
</p>
<p>
Sure enough, a few levels into the API, I spot an examination of the input colorspace, and an objection to the fact that it was only 24-bits per pixel. Great, I thought. If the API knows exactly what&#8217;s wrong, why doesn&#8217;t it let us know <em>somehow</em>, at least through a logging message or something. Then I spotted a  call to &#8220;CGPostError.&#8221; Well, that&#8217;s interesting. A well-defined error reporting mechanism? The results of which the developer never sees? I traced along a while until discovered myself in a logging function, the parameter to which was this choice bit of text:
</p>
<p><pre>
CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component;
	24 bits/pixel; 3-component colorspace; kCGImageAlphaNone.
</pre>
</p>
<p>
Well! It doesn&#8217;t exactly point to the right solution, but it would have been nice to know! Thanks for not sharing, CoreGraphics. Why the heck does it go to all this work and not print out the result? I decided to dig deeper.
</p>
<p>
The framework has an internal function, &#8220;hasTerminal,&#8221; which seems to control whether logging to the console occurs or not. I guess the engineers on the CoreGraphics team are trying to be considerate and not spew logging messages all over your console log unless you&#8217;re actually, you know, debugging. Here&#8217;s the kicker &#8211; hasTerminal returns true if you are running from the terminal. All Jon had to do was test his app from the command-line and the exceedingly helpful logging message would have appeared.
</p>
<p>
But the &#8220;hasTerminal&#8221; function returns false when debugging from within Xcode. Bugger that debugger! How does hasTerminal decide whether to allow logging or not? It simply attempts to open &#8220;/dev/tty&#8221; with read/write access. If it is successful, the user must be running from a terminal?  But somehow, when running from within Xcode, this test fails, and therefore logging is not done. I assume this has something to do with Xcode&#8217;s magic terminal-esque window, but the discovery raises two questions:
</p>
<ol>
<li>Should CoreGraphics limit its logging functionality based on assumptions about &#8220;/dev/tty&#8221;?</li>
<li>Should debugging in Xcode impact a target application&#8217;s ability to open &#8220;/dev/tty&#8221;?</li>
</ol>
<p>
These questions are posed in Radar #<a href="rdar://problem/4538344">4538344</a>- &#8220;CoreGraphics logging doesn&#8217;t appear withing Xcode&#8221;.
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/129/coregraphics-log-jam/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Xcode Search Gone Mad</title>
		<link>http://www.red-sweater.com/blog/67/xcode-search-gone-mad</link>
		<comments>http://www.red-sweater.com/blog/67/xcode-search-gone-mad#comments</comments>
		<pubDate>Tue, 13 Dec 2005 17:12:41 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[applebugfriday]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=67</guid>
		<description><![CDATA[I ran into a search problem recently in one of my Xcode projects. Every time I conducted a particular search (in this case, the search term was &#8220;CFString&#8221;), my screen was littered with a series of cascading Xcode exception dialogs that look like this: On the one hand, it&#8217;s great that Xcode goes out of [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css"><!-- .caption { border-style:dashed; border-width:1px; border-color:#BBBBBB; margin-left:20px; padding:10px;}--></style>
<p>I ran into a search problem recently in one of my Xcode projects. Every time I conducted a particular search (in this case, the search term was &#8220;CFString&#8221;), my screen was littered with a series of cascading Xcode exception dialogs that look like this:</p>
<p><img src="http://www.red-sweater.com/blog/images/BadXcodeSearch.jpg"/></p>
<p>
On the one hand, it&#8217;s great that Xcode goes out of its way to convey internal exceptions to the user. It means that they are less likely to just &#8220;let slide&#8221; exceptional conditions that would otherwise show up only in an archaeological dig through the system&#8217;s console log. On the other hand, when they spray dozens of them out at me while I&#8217;m just trying to search my project, it gets to be a real hassle to close them all after every search.
</p>
<p>
When I run into these kinds of errors from Xcode, I immediately start thinking of where my latest project backup is. It&#8217;s <em>probably</em> some kind of internal project format corruption. The last thing any of us wants to do is trash a project file and start from scratch, so it&#8217;s a good idea to keep backups of the project files (probably along with all your other sources, in the Subversion repository).
</p>
<p>
In this case I thought I&#8217;d be curious and try to get to the bottom of the problem. Since each of these dialogs corresponds to a raised NSException inside Xcode, I thought I&#8217;d attach with gdb and see what&#8217;s going on at the point of exception. This is what the top of the stack looks like while one of the annoying dialogs is being generated:</p>
<div class="caption">
<pre>
#0  0x928f9508 in -[NSException raise] ()
#1  0x95464098 in -[TSException raise] ()
#2  0x928f935c in +[NSException raise:format:] ()
#3  0x929c1794 in mutateError ()
#4  0x928e7a00 in -[NSCFString replaceCharactersInRange:withString:] ()
#5  0x928e7968 in -[NSConcreteMutableAttributedString replaceCharactersInRange:withString:] ()
#6  0x928f2a60 in -[NSConcreteMutableAttributedString initWithString:attributes:] ()
#7  0x98fc1004 in -[PBXFindResult initWithBookmark:textBookmarkResolvable:] ()
#8  0x98fc0e58 in -[PBXReferenceBasedBatchFinder reportBookmarks:findable:] ()
#9  0x98fbff3c in -[PBXTextBatchFinder doSomeFinding] ()
#10 0x98fbfd08 in +[PBXBatchFinder _backgroundBatchFinderNotification:] ()
</pre>
</div>
<p>Something to do with bookmarks! Well, I don&#8217;t even have any bookmarks in my project. Did I screw something one of those times I hit Cmd-D instead of Cmd-Shift-D to &#8220;Open Quickly?&#8221; I decide to set a breakpoint on the call to initWithBookmark:textBookmarkResolvable:, along with some exploratory breakpoint commands. I asked gdb to report to me what the bookmark argument looks like (&#8220;po&#8221; is short for &#8220;print-object&#8221;, useful for displaying Cocoa objects). I left my &#8220;raise&#8221; breakpoint, set to automatically continue, so I can tell what kind of circumstances immediately precede it. This is a &#8220;trap the thief&#8221; technique for pinpointing the misbehaving code. I let Xcode run wild and then look at the logged breakpoint information for clues as to what led to the assertion.</p>
<div class="caption">
<pre>
(gdb) b initWithBookmark:textBookmarkResolvable:
Breakpoint 15 at 0x98fc0ed8
(gdb) command 15
Type commands for when breakpoint 15 is hit, one per line.
End with a line saying just "end".
>po $r5
>c
>end
</pre>
</div>
<p>
With the breakpoints in place, I return to Xcode and invoke my troublesome search. Looking back at the logged output in gdb, I see the following snippet (newlines added for readability):</p>
<div class="caption">
<pre>
Breakpoint 15, 0x98fc0ed8 in -[PBXFindResult initWithBookmark:textBookmarkResolvable:] ()
&lt;PBXTextBookmark:0x08133700:rtn=2:fileRef=
&lt;PBXFileReference:0x05e08d80:rtn=61:65562A49085CB7C5007AD50E:name='HackCFSocketStream.h'>
:timestamp=0:char-range={5485,8}:line-range={5485,8}:&lt;range-type-0>={5485,8}>

Breakpoint 14, 0x928f9508 in -[NSException raise] ()
</pre>
</div>
<p>
So, Xcode doesn&#8217;t like &#8220;HackCFSocketStream.h&#8221;? Aside from its obviously questionable name, what has it done so wrong? I take a look at my search results and sure enough, no HackCFSocketStream.h. Not only are the dialogs I&#8217;m getting annoying, they represent missing search results in Xcode!
</p>
<p>
I decide to try to narrow the problem down by doing a limited search on only the &#8220;bad boy.&#8221; I select the HackCFSocketStream.h file in Xcode&#8217;s files and groups tree, and do another search, this time selecting the &#8220;In Selected Project Items&#8221; scope-limiting option.
</p>
<p>
Son of a gun! No error dialog. It must be particular to doing a global search. I switch back to &#8220;In Project&#8221; and search again. No more bug. Gah! I seem to have &#8220;fixed&#8221; the bug by asking Xcode to limit its search scope to only the problematic file.  I tried a few more problematic files, repeating the same identification method with gdb. Same results! Explicitly searching a selected file fixes the bug, apparently forever.
</p>
<p>
I tried to mix up the procedure a little bit. Instead of selecting the problematic file itself, I select the group that contains it. The bug still exists at this scope, but again, as soon as I select only the problematic file and search, the situation is resolved.
</p>
<p>
What I&#8217;m left with is a situation where I have a painstaking, yet effective method of ridding the project of this bug. Unfortunately, I have to wait until I encounter a search term that finds a problematic file. Then I have to identify the file and go in and do the magic cleansing search.
</p>
<p>
I suppose I might try to write a script or something that goes through and explicitly searches each file in the project. Will that clean things up? I should probably just revert to a backup project and hope for the best.</p>
<p><strong>Update &#8211; More data points:</strong>
<ul>
<li>It appears that it&#8217;s not searching the &#8220;problem file&#8221; but actually just viewing it in the Xcode editor that causes it to be &#8220;fixed.&#8221; I guess Xcode is probably reindexing or something when this happens. Rebuilding the index for the entire project does <em>not</em> fix the problem. So I guess I could work around this by writing a script to go through and open an editor window for every file in my project. We&#8217;ll see.</li>
<p>
<li>A &#8220;problem file&#8221; is only problematic for a particular search term (or set of search terms, perhaps). For instance, a search of &#8220;text&#8221; in my source base causes a failure on a given file, but searching for another term present in that file brings it up just fine.</li>
</p>
</ul>
<p><strong>Update 2:</strong> The &#8220;fix&#8221; achieved by selecting an item is not permanent. It turns out that the error occurs only if the &#8220;bad file&#8221; is <em>not currently open</em> in Xcode. By selecting the file, it becomes open and stays open until explicitly closed. By explicitly closing the file (Cmd-Shift-W), I am able to reproduce the error again.</p>
<p>
<h4>Update 3: Case Closed!</h4>
</p>
<p>
My curiosity wouldn&#8217;t let me leave this alone, and I finally tracked down the root cause of the problem. I have produced a very simple test project that exhibits the problem. If you&#8217;re curious, you can download the project <a href="http://www.red-sweater.com/blog/downloads/TestXcodeBug.zip">here</a>. Look at the single source file &#8220;TestSource.cp&#8221; for instructions on how to reproduce. I know enough about this problem now to summarize it in fairly brief form:</p>
<div class="caption">
Xcode produces incorrect search result range for terms in closed files preceded by multibyte UTF8 characters.</div>
</p>
<p>
I tried to get it shorter than that, but I can&#8217;t! So what&#8217;s the bottom line? If your source file contains a multi-byte UTF8 character, Xcode mistakenly tallies the bytes instead of the characters when computing the offset into that line. In most cases, this just means that the contextual highlighting of the search result is slightly off, but if the &#8220;overshoot&#8221; caused by these multi-byte characters causes a search result range to exceed the end of the line, then it causes the very unsavory runtime exception I&#8217;ve described in this article.
</p>
<p>
This is better demonstrated by example. For instance, in the test project I&#8217;ve linked to, the UTF8 encoded source file contains a line like this:</p>
<div class="caption">
// &#8226;DCJ&#8226; Bullets are dangerous.
</div>
<p>Each of those bullets surrounding my initials is encoded in the file by the UTF8 bytes &#8220;e2 80 a2&#8243;. So what happens if I do a search for &#8220;Bullets&#8221; in this project? If the file is <em>open</em>, I get the expected result:
</p>
<p><img src="http://www.red-sweater.com/blog/images/XcodeBulletsOpen.jpg"/></p>
<p>
But if the file is <em>closed</em>, Xcode is not so savvy and interprets the file apparently on a &#8220;byte == character&#8221; basis:
</p>
<p><img src="http://www.red-sweater.com/blog/images/XcodeBulletsClosed.jpg"/></p>
<p>
See how the emboldened portion of the result is exactly 4 characters &#8220;too far?&#8221; That&#8217;s because the two bullets take 6 bytes, and Xcode assumes that two bullets should take only 2 bytes. The difference is the &#8220;slop&#8221; that gets inappropriately added into the range.
</p>
<p>
When the slop in the range takes you beyond the scope of the line, you get an exception. If I search the project for &#8220;danger&#8221;, I observe the edge case, beyond which no further range can be safely returned for the given line:
</p>
<p><img src="http://www.red-sweater.com/blog/images/XcodeBulletsDanger.jpg"/></p>
<p>Searching for &#8220;dangerous&#8221; is just that. You&#8217;ll end up witnessing one of Xcode&#8217;s friendly error dialogs.</p>
<p>
In summary: any UTF multi-byte character in your source file steals &#8220;safely searchable&#8221; characters from the end of the line. If any search in your project yields results that are at the ends of lines with multibyte characters, you will likely witness an exception and fail to see your search in the resulting pane.
</p>
<p>
Radar <a href="rdar://problem/4377633.">4377633</a>.</p>
<p>
Workaround: Save your source files as some other encoding than UTF8. I don&#8217;t really know which encoding is best. I guess I need to figure this out. For this particular project, which had become a mish-mash of UTF8 and MacRoman encoded files, I decided to switch all the UTF8 files back to MacRoman. I won&#8217;t be able to initialize UTF8 strings with non-MacRoman typed constant values, but at least I&#8217;ll be able to search my project in peace!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/67/xcode-search-gone-mad/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>A Mighty Mistake</title>
		<link>http://www.red-sweater.com/blog/61/a-mighty-mistake</link>
		<comments>http://www.red-sweater.com/blog/61/a-mighty-mistake#comments</comments>
		<pubDate>Wed, 30 Nov 2005 18:57:14 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[applebugfriday]]></category>
		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=61</guid>
		<description><![CDATA[I recently had the opportunity to give Apple&#8217;s Mighty Mouse a good test-drive. I was really excited when this mouse was announced. What a perfect compromise: a two-button mouse that can masquerade as a single-clicker for the frightened masses! My excitement turned to slight concern as the informal reviews started appearing on the web. People [...]]]></description>
			<content:encoded><![CDATA[<p>I recently had the opportunity to give Apple&#8217;s <a href="http://www.apple.com/mightymouse/">Mighty Mouse</a> a good test-drive. I was really excited when this mouse was announced. What a perfect compromise: a two-button mouse that can masquerade as a single-clicker for the frightened masses! My excitement turned to slight concern as the informal reviews started appearing on the web. </p>
<p>
People were discovering a cheezy implementation detail that required the user to completely remove their finger from the left side of the mouse before attempting to click the right side. It was hard to gauge how problematic this issue actually was. The reviewers were either completely appalled by the problem or absurdly nonplussed: &#8220;It&#8217;s no big deal, you just lift your left finger every time you click.&#8221;  No big deal!?
</p>
<p>
Earlier this month I was working in New York for a week on-site with a client. They had bought an awesome new PowerMac G5 for this work, and I was delighted (but a little scared) to see that it came with a Mighty Mouse. To Apple&#8217;s credit, the computer ships with the mouse in &#8220;one button&#8221; mode. This is how they should continue shipping computers. In fact, they should remove the software that allows two-button mode to be enabled. This &#8220;feature&#8221; of the mouse is a total piece of poop. With the Mighty Mouse, essentially every click becomes a Russian roulette gamble. Did I click on the right side or the left side? Well, I <em>know</em> what side I clicked, but what side has the mouse decided I clicked?
</p>
<p>
I battled with the mouse for a few hours, trying to master the art of right clicking. Not only did the mouse fail to register my right clicks half of the time, the monstrosity managed to on occasion turn my left clicks into right clicks! I could swear it even swallowed clicks sometimes!
</p>
<p>
Just how bad is the Mighty Mouse? I have been using a two-button mouse on the Mac for about 5 years. I am completely accustomed to right-clicking everything in sight. I <em>depend</em> on the right mouse button, and I disabled it for my week with the Mighty Mouse. I became a control-clicker for the week!
</p>
<p>
It depresses me that this is the new &#8220;Standard Mouse&#8221; for Macs. It could have been so good. In my opinion it would be false advertising to call this a two-button mouse. I guess that&#8217;s why they just say it has &#8220;multibutton charm.&#8221;</p>
<p>
For those of you who are concerned that the right clicking with the Mighty Mouse <em>might</em> be a problem, but are considering a purchase anyway: <em>save yourself!</em> I&#8217;m back at home with my utterly unstylish Wacom mouse, and loving every damned predictable right click I make.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/61/a-mighty-mistake/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Fixing Keychain &#8211; Look Ma, No Code!</title>
		<link>http://www.red-sweater.com/blog/52/fixing-keychain-look-ma-no-code</link>
		<comments>http://www.red-sweater.com/blog/52/fixing-keychain-look-ma-no-code#comments</comments>
		<pubDate>Thu, 03 Nov 2005 20:42:12 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[applebugfriday]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=52</guid>
		<description><![CDATA[While waiting for Apple to fix the many bugs that I described in my recent posting, I thought I&#8217;d hack in with Interface Builder and fix some of my gripes myself. For the benefit of anybody who shares my grievances, I describe the process here for fixing several of the problematic behaviors. Note: This is [...]]]></description>
			<content:encoded><![CDATA[<p>While waiting for Apple to fix the many bugs that I described in my <a href="http://www.red-sweater.com/blog/?p=51">recent posting</a>, I thought I&#8217;d hack in with Interface Builder and fix some of my gripes myself. For the benefit of anybody who shares my grievances, I describe the process here for fixing several of the problematic behaviors.</p>
<p>
<div style="border-style:dashed; border-width:1px; background-color:#FFFFCC; padding:3px;">
Note: This is risky business. Modifying system files. Don&#8217;t proceed with the operations described below unless you&#8217;re both exceedingly confident you will not make a mistake, and exceedingly confident you&#8217;ll be able to repair it when you do make a mistake. As a rule, modifying Apple&#8217;s products is a bad idea. The changes you make are liable to cause unforeseen side-effects, and will be obliterated by any update from Apple that replaces the affected files.</p>
<p>
Think of the instructions below as a sort of entertainment fiction. You like to watch movies and read books where the characters steal, pillage, murder, take dangerous drugs, etc. Enjoy the thrill of my dangerous activities vicariously. And if you decide to mimic these bad habits in the privacy of your own house, don&#8217;t tell us about it! (Unless you have a really good idea).</p>
</div>
<h3>Preparing to Hack</h3>
</p>
<p>
As with all modifications of Apple-provided applications, it&#8217;s a good idea to start by making a backup for safety&#8217;s sake. In the case of Keychain Access, you&#8217;ll discovery quickly that it&#8217;s not as simple as making a copy of the application in the Finder. It will warn you that &#8220;special permissions&#8221; prevent everything from being copied. There are two things at work here. First, the Keychain Access application and everything inside it is owned by root. Second, there are files inside the package with a &#8220;setuid&#8221; bit set, meaning that when they run, they get to inherit the privileges of root. To make this easy, I suggest in this case only backing up the &#8220;Resources&#8221; portion of the bundle, because that&#8217;s all I&#8217;m going to be modifying. You might get some complaints from Interface Builder that the nibs are &#8220;read only.&#8221; I just saved a copy and then copied the new nib into the English.lproj directory of Keychain Access.</p>
<h3>Applying the Changes</h3>
</p>
<p>
Alleviating the broken &#8220;next responder&#8221; loop in the main Keychain window was as simple as defining an &#8220;initial first responder&#8221; for the window, and setting up an appropriate chain of &#8220;nextKeyView&#8221; connections.  It seems that the responder chain as it ships from Apple is simply the default &#8220;emergency chain&#8221; fabricated by Cocoa when a developer doesn&#8217;t specify a particular chain.  I decided to make mine start with the search field, and advance clockwise through the main table, &#8220;Category table&#8221; and &#8220;Keychain&#8221; table. The MasterView nib file contains the window whose contents can be fixed in this way.
</p>
<p>
While poking around in the MasterView nib, I also decided to change the keyboard shortcut for the &#8220;Info&#8221; button from Cmd-I to simply return. This has the effect of making the return key always open the item selected in the main table, which is fine because the return key doesn&#8217;t do anything special in the other tables in the window that can receive focus.
</p>
<p>
To give a keyboard shortcut to the &#8220;Show Secure Note&#8221; and &#8220;Show Password&#8221; items, I located the corresponding UI elements in the NoteEditor and PasswordEditor nibs. I gave them each the shortcut &#8220;Cmd-T&#8221; (for &#8220;Show <strong>T</strong>ext&#8221;).
</p>
<p>
To alleviate the headaches of the &#8220;Save Changes&#8221; dialog&#8217;s missing keyboard shortcut for &#8220;No,&#8221; I only had to change the Localizable.strings value for that key from &#8220;No&#8221; to &#8220;Don&#8217;t Save,&#8221; which is probably what it should have been in the first place! Keychain Access uses NSBeginCriticalAlertSheet to display the Save Changes dialog, and as advertised, it will automatically accept Cmd-D as a synonym for clicking on the Don&#8217;t Save button. Sometimes &#8220;doing the standard thing&#8221; also means &#8220;doing the right thing,&#8221; and adds up to less work for a better product.
</p>
<p>
Now for the The Big Kahuna. The all-powerful &#8220;Allow Acccess&#8221; keychain authorization dialog. This bad boy&#8217;s unresponsiveness to keystrokes makes it the weak link in not only Keychain Access, but every other application that asks the user to approve a keychain fetch. Where does the Big Kahuna live? By running the command-line tool &#8220;fs_usage&#8221; while invoking the dialog, it&#8217;s easy to locate the nib in question. It looks like /System/Library/CoreServices/SecurityAgent.app/Contents/Resources/English.lproj/ConfirmAccess.nib is what we&#8217;re interested in. Again, the sensitive nature of this application means that I have to be careful to leave most of the existing app in place, while only backing up and modifying the resources.
</p>
<p>
Since I&#8217;m usually more interested in giving applications access &#8220;forever,&#8221; I not only added keyboard shortcuts, but moved things around a bit. I renamed the &#8220;Always Allow&#8221; item to &#8220;Allow Forever,&#8221; made it the default button, and moved it to the far-right. I gave the &#8220;Allow Once&#8221; button the simple shortcut of the &#8220;O&#8221; key. For some reason I was unable to give it a shortcut that requires the Cmd key to be held down. I&#8217;ll take what I can get! The resulting dialog looks like this:
</p>
<p><img src="http://www.red-sweater.com/blog/images/BetterKeychain.jpg"/></p>
<p>
And hallelujah! I can just &#8220;hit return&#8221; when it pops up.
</p>
<p>
The only item in my list of gripes which I haven&#8217;t been able to address in one way or another is the &#8220;Close All Windows&#8221; function. If Keychain Access were scriptable, it would be easy to write a script to workaround the problem, similarly to how I solved the problem in Terminal. As it is, I don&#8217;t expect to open up 500+ info winodws in Keychain Access in the near future, so I think I can live with that shortcoming.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/52/fixing-keychain-look-ma-no-code/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Keychain Inaccessibility</title>
		<link>http://www.red-sweater.com/blog/51/keychain-inaccessibility</link>
		<comments>http://www.red-sweater.com/blog/51/keychain-inaccessibility#comments</comments>
		<pubDate>Thu, 03 Nov 2005 19:03:08 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[applebugfriday]]></category>
		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=51</guid>
		<description><![CDATA[Apple&#8217;s 10.4.3 update includes a nice surprise: the search field for the Keychain Access application is now case-insensitive! How many times I&#8217;ve fumed and fussed about this shortcoming. At last I can search for &#8220;etrade&#8221; and find a note called &#8220;ETrade info.&#8221; Though vastly improved, by no means is the Keychain Access application perfect. In [...]]]></description>
			<content:encoded><![CDATA[<p>Apple&#8217;s 10.4.3 update includes a nice surprise: the search field for the Keychain Access application is now case-insensitive! How many times I&#8217;ve fumed and fussed about this shortcoming. At last I can search for &#8220;etrade&#8221; and find a note called &#8220;ETrade info.&#8221;
<p>
Though vastly improved, by no means is the Keychain Access application perfect. In fact, this application and associated technologies are one of those &#8220;treasure troves&#8221; of undesirable behaviour. Often while looking more carefully at an unfortunate behavior, with the intention of reporting a bug, my attention ends up snowballing into a series of observations of how an application could be better designed.</p>
<p>
With Keychain Access, a major area it is still lags in is the keyboard navigation department. Now that I can easily search my keychain items, it would be nice to be able to do so without ever reaching for the mouse. At this point I have a keyboard shortcut set up to open Keychain Access, and from within the application I can press Cmd-F to start a new search. But when I see the beautiful shining result in the filtered list, there&#8217;s no way to navigate back to it! Pressing Tab from the search field does exit the search field, but it switches focus to the &#8220;Keychains&#8221; sidebar table. Who wants to navigate to that? Pressing Tab again switches focus to the &#8220;Category&#8221; table. Arrow-keying through the various items in this table causes a live update of the main table, but no amount of tabbing will get you there. It&#8217;s a &#8220;next responder dead end!&#8221; (Radar <a href="rdar://problem/4327828">4327828</a>).
</p>
<p>
Once I&#8217;m focused on the main table, there are other hiccups. It took me a while to figure out that I can in fact bring up the secure item&#8217;s &#8220;info dialog&#8221; by pressing Cmd-I. This shortcut is attached to little &#8220;i&#8221; button at the bottom of the screen, and unfortunately is not available from any menu item. The friendliest way to handle this would be to have the tableview interpret &#8220;return key&#8221; as a signal to &#8220;open the selection.&#8221; The return key is often interpreted as a request to either open or edit a selected item. In this case, by opening the Info dialog, it would do both. (Radar <a href="rdar://problem/4327871">4327871</a>).
</p>
<p>
But anyway, at least I can get info! The fun stops there, however. I am looking at the info window, but the thing I want to see: the secure note, web password, whatever, is hidden from me. I can see the checkbox that needs to be clicked to reveal the secrets, but I soooo don&#8217;t want to reach for the mouse. There should be a &#8220;Show Secrets&#8221; keyboard shortcut for any secure item that has such a checkbox. (Radar <a href="rdar://problem/4327842">4327842</a>).
</p>
<p>
In the process of trying to figure out whether there was a convenient shortcut for &#8220;show secrets&#8221; in the info dialog, I managed to stumble into accidentally editing the item. When I closed the item, a dialog came up asking me if I&#8217;d like to save the changes. I tried the typical &#8220;Don&#8217;t Save&#8221; shortcut: cmd-D. No such luck. The &#8220;Save&#8221; button is throbbing blue so its keyboard shortcut is taken care of, but the &#8220;No&#8221; button seems to require a manual mouse click. As a long-shot try, I press &#8220;Cmd-N&#8221; to match the &#8220;No&#8221; of the button&#8217;s text.  At first this seems to work, but instead something very fishy happens. Pressing Cmd-N, even while being faced with a modal sheet in the Info dialog, invokes the application&#8217;s higher-level &#8220;New Keychain Item&#8221; functionality. The Info window and its pending sheet disappear and a sheet appears on the main window asking for details about my new item. I thought the window had been dismissed, but later I found it hiding behind the main keychain window. It had simply been ordered backward. The &#8220;Save Changes&#8221; dialog should support a keyboard shortcut for &#8220;Don&#8217;t Save.&#8221; (Radar <a href="rdar://problem/4327889">4327889</a>).
</p>
<p>
Let&#8217;s assume all the above bugs get fixed, and I&#8217;m sitting pretty in Keychain Access land. I hit my Keychain Access keyboard shortcut, press cmd-F, search for &#8220;etrade,&#8221; navigate to the main table, press return to open the item, press a keyboard shortcut to reveal the secret password, and am faced with the &#8220;Keychain Access wants permission&#8221; dialog. First of all, isn&#8217;t this the <strong>Keychain</strong> Access application? I&#8217;ve just unlocked my whole keychain. We&#8217;re staring at my repository of goodies. Can&#8217;t you work out a deal or something? You seem to be &#8220;in good&#8221; with the Keychain. Once you show the secure text for an item, you can choose to &#8220;Always Allow,&#8221; but that only gives permission for that specific item! So you&#8217;ve got to enter the password and click &#8220;Always Allow&#8221; at least once for every freaking item in your keychain. There should at least be a preference for easily saying &#8220;Always give Keychain Access access to secure items.&#8221; (Radar <a href="rdar://problem/4327935">4327935</a>).
</p>
<p>
I thought maybe I could do something spiffy like go in and manually set all of the items to allow Keychain Access to access them. Since you can &#8220;preload&#8221; this setting in the &#8220;Access Control&#8221; pane of an item&#8217;s info window, I thought maybe I could select all of my items and add the same access privilege for Keychain Access to them. Oops! I selected all 500+ items and hit Cmd-I. Now I&#8217;ve got 500+ Info windows cascading across my screen. To add insult to injury, Keychain Access doesn&#8217;t support a &#8220;Close All Windows&#8221; option, though quitting and relaunching did the trick. (Radar <a href="rdar://problem/4327956">4327956</a>).
</p>
<p>
Having to give individual authorization to each and every item wouldn&#8217;t be so bad if the authorization dialog itself wasn&#8217;t so poorly keyboard-navigable. The dialog pops up, asks you to give authorization (by typing of course&#8230; at the keyboard!) and then you have to go over to the mouse to click either the &#8220;Deny,&#8221;"Allow Once,&#8221; or &#8220;Allow Always&#8221; items. Gah! Presumably this is done to prevent somebody accidentally giving permission to a malicious application, but you&#8217;ve <em>got to enter the password before doing so</em>! That gives me plenty of opportunity to think twice before allowing or denying the action. At least the &#8220;Allow Once&#8221; button should be default and automatically clicked upon hitting return from the password dialog. The &#8220;Always Allow&#8221; button should ideally also have some keyboard shortcut. (Radar <a href="rdar://problem/4327981">4327981</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/51/keychain-inaccessibility/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Font Panel Sucks the Life Out of Interface Builder</title>
		<link>http://www.red-sweater.com/blog/37/font-panel-sucks-the-life-out-of-interface-builder</link>
		<comments>http://www.red-sweater.com/blog/37/font-panel-sucks-the-life-out-of-interface-builder#comments</comments>
		<pubDate>Sun, 09 Oct 2005 19:36:39 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[applebugfriday]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=37</guid>
		<description><![CDATA[Normally I find Interface Builder to be pretty snappy. From time to time over the past few months, however, I have encountered periods of time where Interface Builder&#8217;s responsiveness has slowed to a crawl. What the heck! Could my Nib files be getting too complicated for IB&#8217;s scrappy little frame to handle? I doubted it [...]]]></description>
			<content:encoded><![CDATA[<p>Normally I find Interface Builder to be pretty snappy. From time to time over the past few months, however, I have encountered periods of time where Interface Builder&#8217;s responsiveness has slowed to a crawl. What the heck! Could my Nib files be getting too complicated for IB&#8217;s scrappy little frame to handle? I doubted it seriously, considering the complexity of other applications whose Nib files I have known and loved.</p>
<p>
I finally traced it down to an <b>insidious</b>, parasitic relationship between the standard font panel and Interface Builder.
</p>
<p>
It seems that when the Font Panel is enabled, Interface Builder is liable to start choking on things like mouse clicks and drags. I have observed repeated delays of up to 2 or 3 seconds, just to click on a UI element in IB! And this is a on Dual 2.0Ghz G5! Pity the poor iMac user! When the Font panel goes away, responsiveness comes back 100%. If you&#8217;re just a little bit of a clutter-rat, as I am, then you&#8217;re liable to leave your Font Panel open as you forge ahead with your interface design. It never occurred to me that this might be robbing precious minutes from my work day!
</p>
<p>
This problem can be reproduced easily on Mac OS X 10.4.2 with Xcode 2.1 installed. Follow these steps to reproduce the problem yourself and gape in awe:</p>
<ol>
<li>Launch Interface Builder, creating a new &#8220;Cocoa Application&#8221; document.</li>
<li>Observe the quickness with which you can click and change the selection between each of the 4 instance icons:
<p><img border="1" src="http://www.red-sweater.com/blog/images/Instances1.jpg"/></p>
</li>
<li>Press Cmd-T to bring up the Font panel.</li>
<li>Resize the Instances window such that the icons rearrange. For some reason this helps reveal the problem. I don&#8217;t know if this is a caching issue or what:
<p><img border="1" src="http://www.red-sweater.com/blog/images/Instances2.jpg"/></p>
</li>
<li>Now try clicking between the icons again. It may take a few rounds through, but you will soon start to observe hideous delays between mouse click and selection change.</li>
<li>Once you&#8217;ve observed the slowdown, close the Font panel by again pressing Cmd-T. This should return responsiveness to normal levels</li>
</ol>
<p>
This is a small demonstration of what it&#8217;s like to have this kind of delay plague your entire design session. The delay applies to anything clickable, selectable, draggable, etc., in IB. This includes all UI elements in your windows, views, etc.
</p>
<p>
So if you&#8217;ve been plagued by mysterious, dramatic reductions in IB responsiveness. Make sure your Font panel is closed. It may be sucking the life out of IB!
</p>
<p>
I&#8217;d be interested to hear if any readers can or cannot reproduce this on their own machines. For now I&#8217;m assuming it&#8217;s widespread, and I&#8217;ve reported it as <a href="rdar://problem/4293149">Radar  4293149</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/37/font-panel-sucks-the-life-out-of-interface-builder/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Lazy Parent Views</title>
		<link>http://www.red-sweater.com/blog/35/lazy-parent-views</link>
		<comments>http://www.red-sweater.com/blog/35/lazy-parent-views#comments</comments>
		<pubDate>Thu, 06 Oct 2005 17:10:08 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[applebugfriday]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Debugging]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=35</guid>
		<description><![CDATA[As a Cocoa programmer, it&#8217;s easy to take for granted some of the powerful features of the framework. For instance, autoresizing subviews are a godsend! This is the feature that allows for all of those amazing Interface Builder demos where a few flags are set on the buttons and text views in a window, and [...]]]></description>
			<content:encoded><![CDATA[<p>As a Cocoa programmer, it&#8217;s easy to take for granted some of the powerful features of the framework. For instance, autoresizing subviews are a godsend! This is the feature that allows for all of those amazing Interface Builder demos where a few flags are set on the buttons and text views in a window, and they automatically resize and position themselves while their window gets resized willy-nilly by the user.</p>
<p>
This cool effect depends on a chain of willingness by NSView to &#8220;pass along resize fever.&#8221; When a view gets resized, it optionally asks all of its children to resize, and they ask their children to do the same. If a &#8220;lazy&#8221; parent chooses not to pass the message along to its children, resizing below that node doesn&#8217;t take place. Fortunately, NSViews are by default documented to be &#8220;ambitious&#8221; in this regard.
</p>
<p>
I was recently confused and perplexed by a failure of my custom views to react to the containing window&#8217;s resizing. These views are dynamically added to an empty window just after it has been loaded from a Nib, after which time I expect them to behave according to their preset resizing flags. The empty window has a very simple view hierarchy: just a plain-jane NSView designated to hold the contents of the window (which also has as a superview the window&#8217;s frame). Every time I&#8217;ve ever created a window in Interface Builder, the resizing has worked as expected. <b>This time it doesn&#8217;t.</b></p>
<p>
I double check the resizing flags on my subviews &#8211; everything is order. But they don&#8217;t respond to resizing the window! When the window resizes, the contentView of the window should resize, and my custom subviews should resize/reposition.  That&#8217;s how things work! To see whether it&#8217;s something funky about my custom view, I decide to test a basic resizing scenario by adding an arbitrary subview to my empty window. I choose an NSButton and place it in the upper-right corner of my window, with its autosizing mask set so that it stays there. I run my program, and lo and behold, now *everything* works, including my custom subviews! The mere presence of the button has cured my woes. But I don&#8217;t want to leave a bogus button (or other view) in my window just to work around this problem.
</p>
<p>
I finally get the bright idea of checking the &#8220;autoresizesSubviews&#8221; flag of the window&#8217;s contentView. If somebody is responsible for setting this flag to YES, I&#8217;d like to know who it is, so I can convince them to do it for me! I add a breakpoint on NSView&#8217;s setAutoresizeSubviews: method, and relaunch my application (with the test button still in place). I land in AppKit&#8217;s nib loading code, where I confirm that parameter is YES:</p>
<div style="margin-left:1cm">
<pre>
#0  0x9364be24 in -[NSView setAutoresizesSubviews:] ()
#1  0x9364baf0 in -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] ()
#2  0x93637fc4 in loadNib ()
</pre>
</div>
<p>
I take out the test button to compare notes against my &#8220;broken&#8221; case. Sure enough, without my bogus button, the call to setAutoresizesSubviews never gets called! Could it be that NSView is documented as automatically resizing subviews by default, but in fact depends on being set that way by the Nib loader? Since 99% of the views that people care about resizing probably start their lives in Interface Builder with subviews from the get-go, I suppose it&#8217;s possible. But the documentation says otherwise! Perhaps the documentation writer made an assumption? This is easy to test, especially since I&#8217;m already in gdb. I just create a throwaway NSView object and test the property:</p>
<div style="margin-left:1cm">
<pre>
(gdb) p (BOOL)[[[NSView alloc] init] autoresizesSubviews]
$11 = 1 '\001'
(gdb)
</pre>
</div>
<p><b>Phew!</b> I breathe a sigh of relief to learn that yes, NSView does conform to its documentation. The setting by the Nib loader is just a paranoid double-check, I guess. So who&#8217;s doing me wrong? If a plain-jane NSView comes with autoresizing for free, and my window&#8217;s content view is a plain-jane NSView, then somebody must be setting the flag to NO on my behalf. Damn them! But we just observed that the breakpoint on setAutoresizesSubviews: never gets hit for my window&#8217;s content view. What&#8217;s going on?
</p>
<p>
It becomes clear to me that my window&#8217;s contentView was &#8220;just born wrong.&#8221; In Cocoa, an object that starts out on the wrong foot was probably archived that way. I become very suspicious of Interface Builder, who was responsible for packing up my NSView but apparently included a nasty surprise in the process of doing so. To confirm my suspicions, I attach with gdb to Interface Builder, set a breakpoint on setAutoresizesSubviews, and resave my Nib. Surely this will reveal the wrong-doing. <b>Bzzt!</b> I have tried and tried but witness no call by IB to setAutoresizesSubviews with a &#8220;NO&#8221; parameter.
</p>
<p>
So let&#8217;s review the facts. We&#8217;ve got a situation where an NSView&#8217;s autoresizesSubviews flag turns to NO, but no code on this known planet is culpable (at least through the exposed accessor). If the flag is turning to NO and nobody is calling the accessor, then the odds are that this is an inside job. Why would an NSView turn against itself like that?
</p>
<p>
I try to get NSWindow out of the picture. There are too many potential bullies on this playground. If the problem is that NSView objects without children get freeze-dried in IB and end up without the autoresizing flag set, then I need to simplify the test case. I create an empty NSView in IB by dragging an NSView to my document window. I don&#8217;t do anything to it. Just add an outlet instance var to my window controller, named <i>oBadView</i>. I break on awakeFromNib and examine the simple view from the debugging console:</p>
<div style="margin-left:1cm">
<pre>
(gdb) p (BOOL)[oBadView autoresizesSubviews]
$1 = 1 '\001'
Current language:  auto; currently objective-c
(gdb)
</pre>
</div>
<p>So It&#8217;s <i>not</i> a simple NSView issue.  I further refine the test (and assure myself of sanity) by dropping a fresh NSWindow instance into my nib, and checking its contentView&#8217;s resizesSubviews flag at launch time. It suffers! Well, at least I have a simple way to explain it in the bug report.
</p>
<p>
I don&#8217;t really know where Interface Builder&#8217;s windows come from. I know that if they are instantiated in my nib, there is some voodoo freeze-drying that goes on, somewhat analogous to archiving and unarchiving objects with the NSCoder protocol. But adding a new window to my nib causes no break in NSWindow&#8217;s init methods. I figure there must be some sort of prototype freeze-dried window that gets instantiated and copied as needed to spawn new windows. But this problem is more insidious than that: if I create a window, and add items to the contentView of that window, I end up with the autoresizes flag set to YES. Now if I remove those items, the autoresizes flag is back to NO, even though I never saw a setAutoresizesSubviews call! I think there must be some kind of private IB &#8220;window object&#8221; that gets passed around and mucked with. Perhaps this object is what gets freeze-dried and turned magically into a true NSWindow only after my app launches.
</p>
<p>
I&#8217;m not one to give up easily, but in this case, I admit it: this bug has bested me. Considering the workaround is as easy as sending a &#8220;setAutoresizesSubviews:YES&#8221; message to my window&#8217;s content view at nib awakening, I&#8217;m happy to let the Interface Builder team at Apple figure out the finer details. (<a href="rdar://problem/4290256">Radar 4290256</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/35/lazy-parent-views/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Interprocess Dragging is a Drag (Sometimes)</title>
		<link>http://www.red-sweater.com/blog/33/interprocess-dragging-is-a-drag-sometimes</link>
		<comments>http://www.red-sweater.com/blog/33/interprocess-dragging-is-a-drag-sometimes#comments</comments>
		<pubDate>Fri, 23 Sep 2005 14:33:08 +0000</pubDate>
		<dc:creator>Daniel Jalkut</dc:creator>
				<category><![CDATA[applebugfriday]]></category>

		<guid isPermaLink="false">http://www.red-sweater.com/blog/?p=33</guid>
		<description><![CDATA[My &#8220;Apple Bug Friday&#8221; entries today are both related to a really cool feature of Mac OS X: process switching while dragging. As the operating system has evolved, dragging in general has improved. One of my favorite improvements is that while dragging you can now invoke the Cmd-Tab process switcher keys to bring another application [...]]]></description>
			<content:encoded><![CDATA[<p>My &#8220;Apple Bug Friday&#8221; entries today are both related to a really cool feature of Mac OS X: process switching while dragging. As the operating system has evolved, dragging in general has improved. One of my favorite improvements is that while dragging you can now invoke the Cmd-Tab process switcher keys to bring another application to the front. So instead of performing that tedious &#8220;line up&#8221; to prepare two applications for a drag, you can simply start in one application with the knowledge that you&#8217;ll be able to navigate to the other app before your finger releases the dragged item. I often use this, for instance, when sending attachments through Mail:</p>
<ol>
<li>Locate the attachable files in the Finder.</li>
<li>Select them and start a drag.</li>
<li>Cmd-Tab to activate Mail.</li>
<li>Cmd-N to create a new mail message.</li>
<li>Drop the drag into the content of the new message!</li>
</ol>
<p>
It&#8217;s just &#8230; downright amazing that you can do this! So where are the bugs? There are two major shortcomings I&#8217;ve observed in Apple&#8217;s overall fantastic implementation:
</p>
<p><h4><a href="rdar://problem/4270813">Radar 4270813</a> &#8211; Can&#8217;t cancel drag outside of initiating application</h4>
<p>Normally when you start a drag and end up with second thoughts, you can rely on the effectiveness of the escape key to reject the drag without any worries that you might be accidentally moving a file or object to some new, unfathomable location. For some reason this mechanism simply stops working once you&#8217;ve switched to an application other than the app that originated the drag. So, assuming I want to safely cancel a drag that I&#8217;ve started and then switched applications for, I have to now navigate back to the original application just to hit the escape key and cancel the drag!
</p>
<p>
For instance:</p>
<ol>
<li>Navigate to the Finder and begin dragging a file.</li>
<li>Cmd-Tab to another app, say, Mail.</li>
<li> Hit the escape key. No effect.</li>
<li>Cmd-Tab back to Finder.</li>
<li>Hit the escape key. Drag cancelled!</li>
</ol>
<p>What a drag! The cancel key should kill the drag safely regardless of where the user has wandered. This is especially problematic if, for some reason, your short-term memory fails you and you <i>can&#8217;t remember</i> which application originated the drag.
</p>
<p><h4><a href="rdar://problem/4270824">Radar 4270824</a> &#8211; Can&#8217;t completely switch back to drag-originating app</h4>
<p>So, once you switch back to the originating app you can hit cancel and breathe a sigh of relief. The problem is, switching back to the originating app while the drag is still in place produces another bug, which is that although the originating app is now &#8220;front-most&#8221;, none of its IU (not even its menu bar) has yet been brought to the front. So it&#8217;s not only confusing, but if you decided you wanted to drag to the originating app after all, you&#8217;re out of luck. You&#8217;ll have to cancel the drag and start over.
</p>
<p>
Illustration:</p>
<ol>
<li>Initiate a drag in the Finder by selecting and dragging a file from a folder list.</li>
<li>While keeping the drag alive with the mouse, Cmd-Tab to another application, say Safari.</li>
<li>Decide you don&#8217;t want to drag to Safari after all, and Cmd-Tab back to the Finder.</li>
</ol>
<p>
Result: Although the Finder is somewhat active, none of its windows have come forward, and the menu bar still says &#8220;Safari.&#8221;
</p>
<p>
Workaround: If you can glimpse any part of a Finder window&#8217;s content, then dragging the item to this content and &#8220;moving it around&#8221; seems to trigger full activation of the Finder. I imagine it&#8217;s similar for other applications.
</p>
<p>
What a drag! Cmd-Tabbing to an application should always bring it forward.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.red-sweater.com/blog/33/interprocess-dragging-is-a-drag-sometimes/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

