<?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>Vincent Gable's Blog &#187; Interface Builder</title>
	<atom:link href="http://vgable.com/blog/category/interface-builder/feed/" rel="self" type="application/rss+xml" />
	<link>http://vgable.com/blog</link>
	<description>my weblog.</description>
	<lastBuildDate>Tue, 29 Nov 2011 22:20:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Reverse Engineering Inter-Process Communication</title>
		<link>http://vgable.com/blog/2009/02/05/reverse-engineering-inter-process-communication/</link>
		<comments>http://vgable.com/blog/2009/02/05/reverse-engineering-inter-process-communication/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 17:26:32 +0000</pubDate>
		<dc:creator>Vincent Gable</dc:creator>
				<category><![CDATA[Interface Builder]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Reverse Engineering]]></category>
		<category><![CDATA[IPC]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://vgable.com/blog/2009/02/05/reverse-engineering-inter-process-communication/</guid>
		<description><![CDATA[Matt Gallagher tells how he reverse engineered the link between Xcode and Interface Builder. Very interesting, I learned a lot. I&#8217;ve done essentially the same thing with iChat. (And in retrospect it might have been a bad idea, because it&#8217;s broken on Snow Leopard).]]></description>
			<content:encoded><![CDATA[<p><a href="http://cocoawithlove.com/2009/02/interprocess-communication-snooping.html">Matt Gallagher tells how he reverse engineered the link between Xcode and Interface Builder</a>.  Very interesting, I learned a lot.  I&#8217;ve <a href="http://imlocation.wordpress.com/2007/11/01/interfacing-with-hacking-ichat-in-leopard/">done essentially the same thing with iChat.</a>  (And in retrospect it might have been a bad idea, because it&#8217;s broken on Snow Leopard).</p>
]]></content:encoded>
			<wfw:commentRss>http://vgable.com/blog/2009/02/05/reverse-engineering-inter-process-communication/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Always Update the View From the Main Thread</title>
		<link>http://vgable.com/blog/2008/12/26/always-update-the-view-from-the-main-thread/</link>
		<comments>http://vgable.com/blog/2008/12/26/always-update-the-view-from-the-main-thread/#comments</comments>
		<pubDate>Sat, 27 Dec 2008 00:04:21 +0000</pubDate>
		<dc:creator>Vincent Gable</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Bug Bite]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Interface Builder]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Quotes]]></category>
		<category><![CDATA[AppKit]]></category>
		<category><![CDATA[Multi-Core]]></category>
		<category><![CDATA[Threads]]></category>

		<guid isPermaLink="false">http://vgable.com/blog/2008/12/26/always-update-the-view-from-the-main-thread/</guid>
		<description><![CDATA[I wish I&#8217;d read this years ago: AppKit, the GUI framework, is not thread safe. In order for things to work properly, you (almost) always need to update GUI classes from the main thread &#8211;Dave Dribin (slightly edited) I&#8217;ve run into UI + threading problem before, but I&#8217;d just never seen this limitation of AppKit [...]]]></description>
			<content:encoded><![CDATA[<p>I wish I&#8217;d read this years ago:</p>
<blockquote><p> <strong>AppKit, the GUI framework, is not thread safe. In order for things to work properly, you (almost) always need to update GUI classes from the main thread</strong></p></blockquote>
<p>&#8211;<a href="http://www.dribin.org/dave/blog/archives/2008/05/22/invoke_on_main_thread/">Dave Dribin</a> (slightly edited)</p>
<p>I&#8217;ve <a href="http://vgable.com/blog/2008/05/14/nsalert-sheets-threads-inexplicable-bugs/">run into UI + threading problem before</a>, but I&#8217;d just never seen this limitation of AppKit spelled out.</p>
<p><a href="http://www.dribin.org/dave/blog/archives/2008/05/22/invoke_on_main_thread/">Dave&#8217;s article explains how to call code on the main thread</a> better then I can.</p>
]]></content:encoded>
			<wfw:commentRss>http://vgable.com/blog/2008/12/26/always-update-the-view-from-the-main-thread/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Undocumented Automator.framework Goodness: Actions Library</title>
		<link>http://vgable.com/blog/2008/12/19/undocumented-automatorframework-goodness-actions-library/</link>
		<comments>http://vgable.com/blog/2008/12/19/undocumented-automatorframework-goodness-actions-library/#comments</comments>
		<pubDate>Fri, 19 Dec 2008 20:51:56 +0000</pubDate>
		<dc:creator>Vincent Gable</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Interface Builder]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Reverse Engineering]]></category>
		<category><![CDATA[AMLibraryPanel]]></category>
		<category><![CDATA[AMLibraryView]]></category>
		<category><![CDATA[AMWorkflowController]]></category>
		<category><![CDATA[AMWorkflowView]]></category>
		<category><![CDATA[Automator]]></category>
		<category><![CDATA[Bad Idea?]]></category>

		<guid isPermaLink="false">http://vgable.com/blog/2008/12/19/undocumented-automatorframework-goodness-actions-library/</guid>
		<description><![CDATA[In Leopard, Apple introduced AMWorkflowView and AMWorkflowController, which let you easily add automator-editing capabilities to your application (modulo bugs!) Obviously, for editing a workflow to be useful, you need to be able to add actions to it. And to do that, you need to be able to browse and search actions. But the current Automator.framework [...]]]></description>
			<content:encoded><![CDATA[<p>In Leopard, Apple introduced <a href="http://developer.apple.com/DOCUMENTATION/AppleApplications/Reference/AMWorkflowView_Class/Reference/Introduction.html"><code>AMWorkflowView</code></a> and <a href="http://developer.apple.com/DOCUMENTATION/AppleApplications/Reference/AMWorkflowController_class/index.html"><code>AMWorkflowController</code></a>, which let you easily add automator-editing capabilities to your application (modulo <a href="http://vgable.com/blog/2008/12/18/automator-bugs/">bugs!</a>)</p>
<p>Obviously, for editing a workflow to be useful, you need to be able to add actions to it.  And to do that, you need to be able to browse and search actions.  But the current Automator.framework has no official support for doing this.</p>
<p>But there are undocumented private APIs, which <a href="file://localhost/Applications/Automator.app/">Automator.app (link launches it)</a> uses&#8230;</p>
<h3>How to Find Them</h3>
<p><a href="http://www.codethecode.com/projects/class-dump/">class-dump</a> is an amazingly useful command-line tool that lets you generate headers from a compiled Objective-C binary.  Download it, and point it at <code>/System/Library/Frameworks/Automator.framework/Automator</code>, to see everything Automator.framework <em>really</em> lets you do.</p>
<h3>Instant Library Panel</h3>
<p>The most useful definition I found was,<br />
<code>@interface NSApplication (AMLibraryPanel)<br />
- (void)orderFrontAutomatorLibraryPanel:(id)sender;<br />
@end<br /></code></p>
<p><strong>Calling <code>[NSApp orderFrontAutomatorLibraryPanel:nil];</code> will show a panel with the same action-library view Automator has.<br />
</strong></p>
<p>This is what I&#8217;m using right now in <a href="http://vincentgable.com/imlocation/">IMLocation</a> to let people find actions for workflows.  I don&#8217;t like the idea of using private APIs.  But I like the idea of implementing my own <code>AMLibraryView</code> replacement even less.  It would be a <em>lot</em> of work to make it as good as the real thing.  Any differences give users a fractured experience &#8212; one way to do something in Automator, another in my program.  And I would get dismal ROI, because I expect Apple to expose this functionality in the (near) future.</p>
<p>(I also wouldn&#8217;t be so bullish on using private APIs if I didn&#8217;t have workarounds in place right now.  The only way <code>orderFrontAutomatorLibraryPanel:</code> gets called is if a user presses a &#8220;Show Actions&#8221; button on the toolbar.  That same toolbar has an &#8220;Open in Automator&#8221; button that opens the worklfow in Automator, where they can edit it without bugs.  So even if <code>orderFrontAutomatorLibraryPanel:</code> stopped working tomorrow, users could still do everything they could before &#8212; albeit less elegantly).</p>
<h3>Looking Just Like Automator</h3>
<p><strong>I don&#8217;t recommend doing this</strong>, but I&#8217;ve been able to embed an <code>AMLibraryView</code> in an <code>NSSplitView</code> next to an <code>AMWorkflowView</code>, to get a more Automator.app-like appearance.</p>
<p>Here&#8217;s how I did it, given the <code>IBOutlet</code>s <code>workflowViewAndLibrarySplitView</code> which is an <code>NSSplit</code> view with an <code>AMWorkflowView</code> in one side, and the other side&#8217;s view connected to the outlet <code>workflowLibraryView</code>,</p>
<p><code>[workflowViewAndLibrarySplitView replaceSubview:workflowLibraryView with:[[AMLibraryPanel sharedLibraryPanel] _libraryView]];</code></p>
<p>Will put the library view inside your split view.</p>
<p>Of course this screws up <code>orderFrontAutomatorLibraryPanel:</code>.  And I would not expect it to work in two windows.  And it&#8217;s using an underscore-private method of an already private and undocumented API.  That&#8217;s just to too risky for me; so I stick with the panel.  It gets the job done with one line of code, and that&#8217;s good enough for me.</p>
]]></content:encoded>
			<wfw:commentRss>http://vgable.com/blog/2008/12/19/undocumented-automatorframework-goodness-actions-library/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>One assert() You Need?</title>
		<link>http://vgable.com/blog/2008/12/12/one-assert-you-need/</link>
		<comments>http://vgable.com/blog/2008/12/12/one-assert-you-need/#comments</comments>
		<pubDate>Sat, 13 Dec 2008 03:48:13 +0000</pubDate>
		<dc:creator>Vincent Gable</dc:creator>
				<category><![CDATA[Bug Bite]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Interface Builder]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[assert]]></category>
		<category><![CDATA[Bad Idea?]]></category>
		<category><![CDATA[IBOutlet]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://vgable.com/blog/2008/12/12/one-assert-you-need/</guid>
		<description><![CDATA[Accidently disconnected outlets in shipping Cocoa apps are legend. &#8211; Jonathan &#8220;Wolf&#8221; Rentzsch From what I can tell assert() is slowly going the way of the goto in the programming world. Exceptions, unit-tests, and other modern software engineering practices, seem to have a better answer for testing something at runtime, and ensuring that you never [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Accidently disconnected outlets in shipping Cocoa apps are legend.</p></blockquote>
<p>&#8211;<a href="http://rentzsch.com/papers/loveHateObjC"> Jonathan &#8220;Wolf&#8221; Rentzsch</a></p>
<p>From what I can tell <code>assert()</code> is slowly going the way of the <code><a href="http://en.wikipedia.org/wiki/Goto#Criticism_of_goto_usage">goto</a></code> in the programming world.  Exceptions, unit-tests, and other modern software engineering practices, seem to have a better answer for testing something at runtime, and ensuring that you never enter a bad state.</p>
<p>But there is one case where I think you should put an <code>assert()</code>  (and <a href="http://vgable.com/blog/2008/12/04/nsassert-considered-harmful/"><em>not</em> an <code>NSAssert()</code></a>) in your code: <strong>in <code>awakeFromNib</code> <code><a href="http://vgable.com/blog/2008/12/04/nsassert-considered-harmful/">assert()</a></code> that every <code>IBOutlet</code> is connected</strong>.</p>
<p>It&#8217;s surprisingly easy to accidentally disconnect something in Interface Builder, or rename something in Xcode.  I&#8217;ve done it before.  More then once.  <code>assert()</code>-ing <code>IBOutlet</code>s has saved me a lot of debugging time.</p>
<h3>Hard to Find In Code</h3>
<p>An <code>IBOutlet</code> that is not connected is <code>nil</code>.  Because <a href="http://vgable.com/blog/2008/05/31/messages-to-nowhere/">Objective-C quietly ignores messages sent to <code>nil</code></a>, it&#8217;s very easy not to notice the problem for a while; then spend a long time debugging a side effect of the issue.</p>
<h3>Hard to Find By Eye</h3>
<p>A widget in a nib/xib file that is not connected will never change it&#8217;s state.  But it typically it has a reasonable initial state.  This makes it difficult to detect disconnected <code>IBOutlet</code>s by eye, because things will look right until they are supposed have changed, but the eye is drawn to change, and de-emphasizes unchanging things.</p>
<h3>Why <code>assert()</code>?</h3>
<p>As Wolf says, the worst-case-scenario is that right before release you make a trivial change in Interface Builder (&#8220;We can&#8217;t ship with that window saying &#8220;Claculator&#8221;), an <code>IBOutlet</code> gets disconnected, and nobody notices in time.</p>
<p>But an <code>assert()</code> failing will be noticed with casual testing, and triggered if the nib is loaded at all, even if the series of interactions needed to cause the widget to change state are not performed.</p>
<p>An <code>assert()</code> is very light-weight and easy to do.  It&#8217;s exactly one line of code, and you don&#8217;t have to add a unit testing framework to your project to do it.  And that makes it perfect for test projects.  I&#8217;m a believer in getting a feature working in a test project first, then copying it into your real product.  (Honestly I don&#8217;t do it as much as I should, and I almost always kick myself for it.)  It lets you test and learn without hacking-up your product.  Plus, new things are often easier to try without the weight of a big code base.</p>
<p>Speaking of unit tests, <del>I don&#8217;t have complete faith in them here. That&#8217;s because a disconnected <code>IBOutlet</code> in a shipping program is fundamentally an issue with <em>the way the release-build is configured.</em>  So anything that&#8217;s not testing <em>the the actual release build</em> is <em>not</em> exhaustively testing for this problem.</del> an <a href="http://developer.apple.com/tools/unittest.html">OCUnit-test</a> can catch a disconnected <code>IBOutlet</code> if it is loaded into the application.  But in my experience, such tests are cumbersome. Running them involves launching your full application, and programatically manipulating it.  This can take a while to run since all the UI will be displayed and animated. And you have to be careful about state since each test will be changing the state of your program.</p>
<p>Ultimately,  <code>assert()</code> just seems to be optimal, in dependability and simplicity, for catching a disconnected <code>IBOutlet</code>.</p>
<p>But I suspect there&#8217;s a better way I don&#8217;t know.</p>
<h3>How do <em>you</em> catch <code>IBOutlet</code>s?</h3>
]]></content:encoded>
			<wfw:commentRss>http://vgable.com/blog/2008/12/12/one-assert-you-need/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Two Help Menus</title>
		<link>http://vgable.com/blog/2008/10/29/two-help-menus/</link>
		<comments>http://vgable.com/blog/2008/10/29/two-help-menus/#comments</comments>
		<pubDate>Wed, 29 Oct 2008 14:21:31 +0000</pubDate>
		<dc:creator>Vincent Gable</dc:creator>
				<category><![CDATA[Bug Bite]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Interface Builder]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[AppKit]]></category>
		<category><![CDATA[awakeFromNib]]></category>
		<category><![CDATA[NSApplication]]></category>

		<guid isPermaLink="false">http://vgable.com/blog/2008/10/29/two-help-menus/</guid>
		<description><![CDATA[I ran into an issue at work where sometimes an application would have two &#8220;Help&#8221; menus, on OS X 10.5 &#8220;Leopard&#8221; (but not on OS X 10.4 &#8220;Tiger&#8221;). The problem was interacting with the UI before the application had finished enough of the AppKit-initialization process. The application had to install a component, which involved displaying [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into an issue at work where sometimes an application would have two &#8220;Help&#8221; menus, on OS X 10.5 &#8220;Leopard&#8221; (but not on OS X 10.4 &#8220;Tiger&#8221;).  The problem was interacting with the UI before the application had finished enough of <a href="http://cocoawithlove.com/2008/03/cocoa-application-startup.html">the AppKit-initialization process</a>.</p>
<p>The application had to install a component, which involved displaying authentication dialogs and such.  Because the component was necessary for the application to work correctly, I thought it would be safest to do this as early as possible.  But displaying a dialog in code called from <code><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Protocols/NSNibAwaking_Protocol/Reference/Reference.html#//apple_ref/occ/instm/NSObject/awakeFromNib">awakeFromNib</a></code> ended up being the cause of the double Help Menu issue.</p>
<p>Waiting until <code><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/applicationWillFinishLaunching:">applicationWillFinishLaunching</a>:</code> or <code><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/applicationDidFinishLaunching:">applicationDidFinishLaunching</a>:</code> to interact with the user fixed the problem.  (In my case, it was safe to defer the installation until then.)</p>
<p>I am not aware of any other issues from putting up a window &#8220;too early&#8221; &#8230; however, it seems to me that doing it is asking for trouble.  The AppKit/Cocoa environment obviously isn&#8217;t 100% ready at that point.  Why risk running your code with half-baked libraries if you don&#8217;t have to?</p>
<p>Whenever possible, I will defer &#8220;first run&#8221; behavior until <code>applicationWillFinishLaunching:</code> or <code>applicationDidFinishLaunching:</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://vgable.com/blog/2008/10/29/two-help-menus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Localizing In Xcode</title>
		<link>http://vgable.com/blog/2008/08/20/localizing-in-xcode/</link>
		<comments>http://vgable.com/blog/2008/08/20/localizing-in-xcode/#comments</comments>
		<pubDate>Wed, 20 Aug 2008 18:38:49 +0000</pubDate>
		<dc:creator>Vincent Gable</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Interface Builder]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Quotes]]></category>
		<category><![CDATA[Usability]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[Internationalization]]></category>
		<category><![CDATA[L10n]]></category>
		<category><![CDATA[Localization]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://vgable.com/blog/2008/08/20/localizing-in-xcode/</guid>
		<description><![CDATA[Let me say this again in slow motion: NEVER type in ANY English string without typing NSLocalizedString() around it! This will save you SO MUCH HASSLE later on when your app is popular. Remember that enterprising polyglots can localize your code from just the binary you ship if you follow a few rules of localization, [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Let me say this again in slow motion: <strong>NEVER type in ANY English string without typing <code>NSLocalizedString()</code> around it!</strong> This will save you SO MUCH HASSLE later on when your app is popular. Remember that enterprising polyglots can localize your code from <em>just the binary you ship</em> if you follow a few rules of localization, so you may wake up one day and find that someone from across the world has mailed you a your app in another language. It&#8217;s a fuzzy feeling and it gets you instant market-share.
</p></blockquote>
<p>&#8211;<a href="http://www.wilshipley.com/blog/2006/12/pimp-my-code-part-13-pimp-before.html">Wil Shipley</a></p>
]]></content:encoded>
			<wfw:commentRss>http://vgable.com/blog/2008/08/20/localizing-in-xcode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Objects that Won&#8217;t Hide</title>
		<link>http://vgable.com/blog/2008/05/25/objects-that-wont-hide/</link>
		<comments>http://vgable.com/blog/2008/05/25/objects-that-wont-hide/#comments</comments>
		<pubDate>Mon, 26 May 2008 04:10:25 +0000</pubDate>
		<dc:creator>Vincent Gable</dc:creator>
				<category><![CDATA[Bug Bite]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Interface Builder]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://vgable.com/blog/2008/05/25/objects-that-wont-hide/</guid>
		<description><![CDATA[NOTE: Although this specific Bug Bite is about NSTextView, and the &#8220;hidden&#8221; property, the same underlying issue applies to other interface-objects (NSTableView, etc.), and different properties, like size. Problem If you send a setHidden:YES message to an NSTextView, and it&#8217;s text disappears, but the view itself (white box) stays visible here&#8217;s the problem, and the [...]]]></description>
			<content:encoded><![CDATA[<p><em>NOTE: Although this specific <a href="http://vgable.com/blog/category/bug-bite/">Bug Bite</a> is about <code>NSTextView</code>, and the &#8220;hidden&#8221; property, the same underlying issue applies to other interface-objects (<code>NSTableView</code>, etc.), and different properties, like size.</em></p>
<p><strong>Problem</strong>
<p>If you send a <code>setHidden:YES</code> message to an <code>NSTextView</code>, and it&#8217;s text disappears, but the view itself (white box) stays visible here&#8217;s the problem, and the solution.</p>
<p>It turns out that if you created the <code>NSTextView</code> by dragging it off the pallet in Interface Builder, then it&#8217;s not an <code>NSTextView</code>.  It&#8217;s an <code>NSTextView</code> wrapped inside an <code>NSClipView</code> inside an <code>NSScrollView</code>.  The <code>NSScrollView</code> is what puts up the scroll-bars if the <code>NSTextView</code> gets really big; the <code>NSClipView</code> helps make the scrolling work.</p>
<p>So if <code>text</code> is your <code>IBOutlet</code> to your <code>NSTextView</code>, then when you say <code>[text setHidden:YES];</code>, the <code>NSTextView</code> <b>is</b> hidden, but the the total package won&#8217;t disappear, unless you hide the <code>NSScrollView</code> as well.</p>
<p><strong>Solutions</strong>
<p>You can send the message to <code>NSScrollView</code> containing <code>text</code>, like so:<br />
&nbsp;&nbsp;&nbsp;<code>[[text enclosingScrollView] setHidden:YES];</code>.<br />
This will hide everything inside the <code>NSScrollView</code>, including <code>text</code>.</p>
<p>Another solution is to create <em>just</em> an <code>NSTextView</code> in Interface Builder.  To do this, put an <code>NSView</code> in your interface (it&#8217;s called a &#8220;Custom View&#8221;,in the Interface Builder objects pallet).  Then select it, bring up the object inspector (cmd-shift-i), choose the &#8220;custom class&#8221; from the category menu at the top, and select <code>NSTextView</code> from the list of subclasses.  This puts an <code>NSTextView</code> in your interface, without the surrounding clip and scroll views.  Unfortunately, it also means you can&#8217;t configure it in Interface Builder, beyond resizing it.  That&#8217;s why I&#8217;m not partial to this approach, although I have used it.</p>
<p>Thanks to <a href="http://mirasoftware.com/">ZachR</a> for suggesting <code>enclosingScrollView</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://vgable.com/blog/2008/05/25/objects-that-wont-hide/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>NSAlert + Sheets + Threads = Inexplicable Bugs</title>
		<link>http://vgable.com/blog/2008/05/14/nsalert-sheets-threads-inexplicable-bugs/</link>
		<comments>http://vgable.com/blog/2008/05/14/nsalert-sheets-threads-inexplicable-bugs/#comments</comments>
		<pubDate>Thu, 15 May 2008 03:08:02 +0000</pubDate>
		<dc:creator>Vincent Gable</dc:creator>
				<category><![CDATA[Bug Bite]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Interface Builder]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Multi-Core]]></category>
		<category><![CDATA[NSAlert]]></category>
		<category><![CDATA[Threads]]></category>

		<guid isPermaLink="false">http://vgable.com/blog/2008/05/14/nsalert-sheets-threads-inexplicable-bugs/</guid>
		<description><![CDATA[UPDATED 2008-12-26: in general, all AppKit code should be called on the main thread. Problem: When using an NSAlert to display a sheet in a multi-threaded application, unexpected badness can happen. I was using beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo: To display an NSAlert as a sheet. But when the sheet appeared, the window it was attached to disappeared and [...]]]></description>
			<content:encoded><![CDATA[<p>UPDATED 2008-12-26: <a href="http://vgable.com/blog/2008/12/26/always-update-the-view-from-the-main-thread/">in general, <em>all</em> AppKit code should be called on the main thread</a>.</p>
<p><strong>Problem:</strong><br />
When using an <code><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSAlert_Class/index.html"><strong>NSAlert</strong></a></code> to display a <strong>sheet</strong> in a <strong>multi-threaded application</strong>, unexpected badness can happen.</p>
<p>I was using<br />
<a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSAlert_Class/Reference/Reference.html#//apple_ref/occ/instm/NSAlert/beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:"><code>beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:</code></a><br />
To display an <code><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSAlert_Class/index.html">NSAlert</a></code> as a sheet.</p>
<p>But when the sheet appeared, the window it was attached to disappeared and got into some weird broken state where it would appear iff the application was not frontmost.</p>
<p>Fortunately, I remembered <a href="http://imlocation.wordpress.com/2007/10/11/nsalert-sheet-not-having-focus/">having encountered weirdness with <code>NSAlert</code> sheets before</a>.  The symptoms were different (previously the alert didn&#8217;t have focus), but the same solution still worked.</p>
<p><strong>Solution:</strong> make sure the message to display the sheet is sent by the main thread.  To do this, put the call to <code>beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:</code> inside another method, <code>showMyAlert</code>, then use <code>performSelectorOnMainThread:withObject:waitUntilDone:</code> to make sure <code>showMyAlert</code> is called on the main thread.</p>
<p><strong>Work around</strong> use <code>runModal</code> to display the alert as a modal dialog instead of a sheet.  <code>runModal</code> Does not appear to have any problems when called from other threads.</p>
<p><del>Just like <a href="http://imlocation.wordpress.com/2007/10/11/nsalert-sheet-not-having-focus/">last time</a>:</p>
<blockquote><p>The whole incident feels funny to me.  I suspect there may be some deeper issue at work that I am not aware of.  When I have time to investigate further I shall update this post.  Unfortunately I don&#8217;t have time to look into &#8216;solved&#8217; bugs today.</p></blockquote>
<p></del></p>
<p>UPDATED 2008-12-26: <a href="http://vgable.com/blog/2008/12/26/always-update-the-view-from-the-main-thread/">in general, <em>all</em> AppKit code should be called on the main thread</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://vgable.com/blog/2008/05/14/nsalert-sheets-threads-inexplicable-bugs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

