<?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>Cocoa Butter</title>
	<atom:link href="http://www.spikesoft.net/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.spikesoft.net/blog</link>
	<description>Yet another Cocoa development blog</description>
	<lastBuildDate>Sun, 13 May 2012 02:15:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Tracking multiple NSURLConnections</title>
		<link>http://www.spikesoft.net/blog/?p=48</link>
		<comments>http://www.spikesoft.net/blog/?p=48#comments</comments>
		<pubDate>Thu, 31 Mar 2011 16:34:38 +0000</pubDate>
		<dc:creator>Lorenzo</dc:creator>
				<category><![CDATA[Cocoa Bindings]]></category>
		<category><![CDATA[NSArrayController]]></category>
		<category><![CDATA[NSTableView]]></category>
		<category><![CDATA[NSURLConnection]]></category>
		<category><![CDATA[NSURLRequest]]></category>
		<category><![CDATA[Xcode 4]]></category>

		<guid isPermaLink="false">http://www.spikesoft.net/blog/?p=48</guid>
		<description><![CDATA[A couple of years back, when I first started playing with the new Leopard (10.5) ABI&#8217;s, I was looking for a project that would allow me to play around with things like Assocaiated References (AR&#8217;s) and Blocks I spend most of my free time maintaining both Weather Vane and Audio Switcher, which still run under [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of years back, when I first started playing with the new Leopard (10.5) ABI&#8217;s, I was looking for a project that  would allow me to play around with things like <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html">Assocaiated References</a> (AR&#8217;s) and <a href="http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/00_Introduction.html">Blocks</a></p>
<p>I spend most of my free time maintaining both Weather Vane and Audio Switcher, which still run under 10.4 and so can&#8217;t make use of any of the new ABI. After looking at a few of the examples of the new stuff on the &#8216;net, I decided I would try to use them to track multiple NSURLConnections. If you need to create and dispatch multiple, simultaneous NSURLConnections, you&#8217;ll find that the  <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLRequest_Class/Reference/Reference.html">NSURLConnection ABI</a> does not provided a means of distinguishing between the data returned from each connection. One obvious and simple solution to this problem is to subclass NSURLConnection and add some identifying field that distinguishes each connection. I did just this some years back and thought at the time, that it seemed silly to have to do that. So, I thought I&#8217;d redo that project specifically using AR&#8217;s to track each connection. If you read the docs, you know that you can use AR&#8217;s to associate arbitrary data to a given object. When the connection returns data, you inspect the data you associated with it to determine which connection it is and then do whatever you need.</p>
<p>This actually works pretty well, but I wanted to get some opinions from other Cocoa developers about this method of tracking connections. You can read the <a href="http://lists.apple.com/archives/cocoa-dev/2010/Jun/msg01142.html">thread here</a>. Many of the comments were enlightening and gave me a couple more ideas to try. Well, I&#8217;ve finally found the time to re-work the project, but this time, instead of trying to shoehorn some ABI into the project, I tried to accomplish this task in a smarter way.</p>
<p>So, this time I decided to wrap an NSURLConnection in an object that acts as the delegate for its connection. This proved to be much cleaner, as now the connection object essentially tracks itself. Of course, this assumes that each connection needs to handle the returned data in the same way. If different connections need to behave differently, you&#8217;ll need to try something else. The project creates multiple http request and tracks the time it takes for the headers to come back and then how long it takes for the body of the request to completely load. Not exactly sure if how I time the connections is correct, but it&#8217;s neither here nor there for this project. The important part is the connection tracking. Here&#8217;s a screen shot:</p>
<div id="attachment_49" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.spikesoft.net/blog/wp-content/uploads/2011/03/URL-Timer.png"><img class="size-medium wp-image-49" title="NSURLConnection timer" src="http://www.spikesoft.net/blog/wp-content/uploads/2011/03/URL-Timer-300x173.png" alt="" width="300" height="173" /></a><p class="wp-caption-text">NSURLConnection timer</p></div>
<p>Each object is added to an NSArrayController and its fields are mapped to the NSTableView&#8217;s columns. Unlike the first project, though, there is no logic in code to determine which connection is which. As the values change in each connection, <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaBindings/CocoaBindings.html">Cocoa Bindings</a> handles their display, which keeps things nice and clean. You download the project <a href="http://www.spikesoft.net/downloads/URLTimerWithDelegate.zip">here</a>. There is a file &#8220;entries&#8221; included with the project. Its just a plist of http urls you can use to populate the table instead of manually typing in urls, if you prefer. I haven&#8217;t done a line by line comparison of the two projects, but there is at least 30% reduction in code. I&#8217;ve decided not to upload the original project. It  could use a bit of clean up, but if anyone wants to look at it, I&#8217;ll go ahead and post it.</p>
<p>As always, if you have ideas or questions, feel free to post.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spikesoft.net/blog/?feed=rss2&#038;p=48</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Delaying the shutdown sequence</title>
		<link>http://www.spikesoft.net/blog/?p=30</link>
		<comments>http://www.spikesoft.net/blog/?p=30#comments</comments>
		<pubDate>Tue, 30 Mar 2010 00:56:38 +0000</pubDate>
		<dc:creator>Lorenzo</dc:creator>
				<category><![CDATA[NSProcessInfo]]></category>
		<category><![CDATA[applicationShouldTerminate]]></category>
		<category><![CDATA[NSTerminateLater]]></category>
		<category><![CDATA[NSTimer]]></category>
		<category><![CDATA[shutdown]]></category>

		<guid isPermaLink="false">http://www.spikesoft.net/blog/?p=30</guid>
		<description><![CDATA[If the computer is in the process of shutting down, you can delay the shutdown if you need to say, put up a dialog box. If your app has an unsaved document, you need to give the user an opportunity to save, not save, or cancel the shutdown outright. There may be other reasons you [...]]]></description>
			<content:encoded><![CDATA[<p>If the computer is in the process of shutting down, you can delay the shutdown if you need to say, put up a dialog box. If your app has an unsaved document, you need to give the user an opportunity to save, not save, or cancel the shutdown outright. There may be other reasons you need to delay the shutdown. For example, I have a simple program which displays a dialog box reminding my wife and son to turn off the wireless mouse when they shutdown. The dialog doesn&#8217;t have an OK button so it can&#8217;t be dismissed. Instead, I use a timer and a delegate function  -(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender.<br />
When the app is told to shutdown, the delegate function is called and you have three return options:<br />
NSTerminateNow &#8211; which allows the app to quit immediately and the shutdown to continue<br />
NSTerminateCancel &#8211; which cancels the shutdown sequence immediately (You&#8217;ll get the user cancelled dialog box)<br />
NSTerminateLater &#8211; which delays the shutdown sequence for a bit, giving you time to do something, such as putting up a dialog box. If the delay is too long, the shutdown will eventually be canceled. NSTerminateLater also causes your app to be placed a new runloop mode, NSModalPanelRunLoopMode. Now, if you want to use a timer to dismiss the dialog you&#8217;ve put up, such as in my app, you have to take care to place your timer in the NSModalPanelRunLoopMode, otherwise, your timer will never fire. There are 4 class methods for creating an NSTimer:</p>
<p><code><br />
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds<br />
invocation:(NSInvocation *)invocation repeats:(BOOL)repeats</code></p>
<p><code>+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds<br />
target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats</p>
<p>+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)seconds<br />
invocation:(NSInvocation *)invocation repeats:(BOOL)repeats</p>
<p></code></p>
<p><code>+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)seconds<br />
target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats<br />
</code><br />
The first two, automatically place the NSTimer in the default runloop, so if you use either of these in this situation, the timer will never fire. Use one of the last two and then you&#8217;ll need to manually place the timer in the correct runloop, ala,<br />
<code><br />
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSModalPanelRunLoopMode];<br />
</code><br />
Of course, when you initialize your timer, you need to give it a method to invoke. Within the body of that method, you can just this send this message to NSApp passing YES as the lone parameter:<br />
<code><br />
- (void)replyToApplicationShouldTerminate:(BOOL)shouldTerminate<br />
</code><br />
I have a sample app <a href="http://www.spikesoft.net/downloads/TurnOffMouse.zip">here</a>. (The crash issue is now fixed)</p>
<p>One other thing to note is the new &#8220;Sudden Termination&#8221; feature of Snow Leopard (10.6). To speed up shutdown/restart, the OS will immediately terminate an application if it allows for sudden termination. You can read the documentation here in the:</p>
<p><a href="http://tinyurl.com/39yatd3">NSProcessInfo</a> docs.</p>
<p>The upshot of this is that if your app should not abruptly quit (in Snow Leopard), you need to disable sudden termination. You can either do this in code ([[NSProcessInfo processInfo] disableSuddenTermination]) or in the app&#8217;s plist (NSSupportsSuddenTermination NO). Whatever route you choose, you can re-enable sudden termination in code via [[NSProcessInfo processInfo] enableSuddenTermination].</p>
<p>That&#8217;s it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spikesoft.net/blog/?feed=rss2&#038;p=30</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Capitalize first character of an NSString</title>
		<link>http://www.spikesoft.net/blog/?p=24</link>
		<comments>http://www.spikesoft.net/blog/?p=24#comments</comments>
		<pubDate>Sat, 06 Mar 2010 02:05:53 +0000</pubDate>
		<dc:creator>Lorenzo</dc:creator>
				<category><![CDATA[NSString]]></category>
		<category><![CDATA[Capitalization]]></category>
		<category><![CDATA[Category]]></category>

		<guid isPermaLink="false">http://www.spikesoft.net/blog/?p=24</guid>
		<description><![CDATA[While localizing Weather Vane, I found that the non-English forecasts returned from AccuWeather are always returned with the forecast in all lower case. The English forecast returns a string with the first character in the string capitalized; like a sentence. Makes sense to me, so I thought I&#8217;d just find the method in NSString that [...]]]></description>
			<content:encoded><![CDATA[<p>While localizing <a href="http://www.spikesoft.net/downloads.php#wv">Weather Vane</a>, I found that the non-English forecasts returned from <a href="http://www.accuweather.com">AccuWeather</a> are always returned with the forecast in all lower case. The English forecast returns a string with the first character in the string capitalized; like a sentence. Makes sense to me, so I thought I&#8217;d just find the method in NSString that would do that for me.  Well, there isn&#8217;t one, so what did I do? Category time! Here&#8217;s what I did:<br />
<code><br />
-(NSString*) stringWithSentenceCapitalization<br />
{</code></p>
<p><code><br />
NSString *firstCharacterInString = [[self substringToIndex:1] capitalizedString];<br />
NSString *sentenceString = [self stringByReplacingCharactersInRange:NSMakeRange(0,1) withString: firstCharacterInString];<br />
</code></p>
<p><code><br />
return sentenceString;<br />
}<br />
</code></p>
<p>The only gotcha here, if there is one, is that<br />
<code><br />
(NSString *)stringByReplacingCharactersInRange:(NSRange)<em>range</em> withString:(NSString *)<em>replacement</em><br />
</code><br />
is Leopard (10.5) and above only, so if you need to support 10.4 (as I do), you need to do something else.</p>
<p>Here&#8217;s what I did in Weather Vane:<br />
<code><br />
-(NSString*)stringWithSentenceCapitalization:(NSString*)str<br />
{</p>
<p>	// Get the first character in the string and capitalize it.<br />
    NSString *firstCapChar = [[str substringToIndex:1] capitalizedString];</p>
<p>	NSMutableString * temp = [str mutableCopy];</p>
<p>	// Replace the first character with the capitalized version.<br />
    [temp replaceCharactersInRange:NSMakeRange(0, 1) withString:firstCapChar];</p>
<p>    return [temp autorelease];<br />
}<br />
</code></p>
<p>As always, if you find a better way, please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spikesoft.net/blog/?feed=rss2&#038;p=24</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>List of fonts installed on the iPhone/iPad</title>
		<link>http://www.spikesoft.net/blog/?p=21</link>
		<comments>http://www.spikesoft.net/blog/?p=21#comments</comments>
		<pubDate>Fri, 29 Jan 2010 22:04:23 +0000</pubDate>
		<dc:creator>Lorenzo</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[NSTableView]]></category>
		<category><![CDATA[Font]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPhone fonts]]></category>

		<guid isPermaLink="false">http://www.spikesoft.net/blog/?p=21</guid>
		<description><![CDATA[I finally got around to updating this for the iPad. The project is setup for iOS 5.1 and a deployment target of 3.2, but it should open and work in the later versions of Xcode 3. One other point I should add: After converting this to support iPad, I noticed an annoying problem where the [...]]]></description>
			<content:encoded><![CDATA[<p>I finally got around to updating this for the iPad. The project is setup for iOS 5.1 and a deployment target of 3.2, but it should open and work in the later versions of Xcode 3. One other point I should add:<br />
After converting this to support iPad, I noticed an annoying problem where the content of a given cell would &#8220;disappear&#8221; when the cell reappeared in the view after scrolling. Undrawn cells below or above the view would appear empty when first scrolled onto the screen. This only happened when the device, iPhone or iPad, was lying flat on a table. I tracked this down to a couple of issues with my cellForRowAtIndexPath method.<br />
First, never do any more inside the if(cell==nil) clause than is needed in every cell. Remember if the cell is reused, anything inside that clause won&#8217;t get executed when another cell is requested. In this example. All I do is initialize the cell, set the minimum font size and constraint width of the text, every cell needs those. The text, which varies with each cell, is after the &#8216;if&#8217; clause. Also, I had to replace initWithFrame with <a href="http://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html#//apple_ref/occ/instm/UITableViewCell/initWithStyle:reuseIdentifier:">initWithStyle:reuseIdentifier</a>, not sure why I was doing it the other way. The real problem I found is that, for example, when you place an iOS device flat on a table, [[UIDevice currentDevice] orientation] will always return UIDeviceOrientationFaceUp. My code was adding the text without considering this situation, so neither of my if/else clauses was executing, therefore no text. So I just check for landscape orientation and draw the text accordingly, or portrait when face up. That&#8217;s it.</p>
<p>Just a quick post to show how you can get a list of the fonts installed on the iPhone. There are lists available on the internet, but I was bored one day and decided to write an iPhone app that displays them all in a grouped table view subdivided by font family. Its based on some sample code I found <a href="http://ajnaware.wordpress.com/2008/10/24/list-of-fonts-available-on-the-iphone">here</a>. The only problem with that code is that since it outputs the results to the console, you don&#8217;t know how the font actually looks. This little project displays each font string using the font itself. There&#8217;s also a simple example of how to create and initialize a table header view from a xib. Here&#8217;s the <a href="http://www.spikesoft.net/downloads/FontViewer.zip">project</a>. Sample output is here:<br />
<img src="http://www.spikesoft.net/blog_images/FontViewer.jpg" alt="FontViewer output" /></p>
<p>I hope you find this useful.</p>
<p>Done using iOS 5.1 (<em>should </em>work with older SDK&#8217;s and minimum a deployment target of 3.2)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spikesoft.net/blog/?feed=rss2&#038;p=21</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>missing source managed object model</title>
		<link>http://www.spikesoft.net/blog/?p=17</link>
		<comments>http://www.spikesoft.net/blog/?p=17#comments</comments>
		<pubDate>Sun, 17 Jan 2010 06:06:08 +0000</pubDate>
		<dc:creator>Lorenzo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Core Data]]></category>
		<category><![CDATA[Marcus Zarra]]></category>

		<guid isPermaLink="false">http://www.spikesoft.net/blog/?p=17</guid>
		<description><![CDATA[I&#8217;ve been working through the Marcus Zarra book &#8220;Core Data&#8221; and although it seems quite good, I&#8217;ve found a few things that could have been made a bit clearer. As with most any book, there are errors, you can find the errata for the Core Data book here: Core Data errata . But some things [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working through the Marcus Zarra book &#8220;Core Data&#8221; and although it seems quite good, I&#8217;ve found a few things that could have been made a bit clearer. As with most any book, there are errors, you can find the errata for the Core Data book here: <a href="http://pragprog.com/titles/mzcd/errata">Core Data errata</a> . But some things are not as clear as they could be for total novices to CD.  As you follow the book through and build the sample projects (available here: <a href="http://pragprog.com/titles/mzcd/source_code">Core Data source</a>), you might find things don&#8217;t work as the book indicates they should.</p>
<p>I&#8217;m going to assume you can figure out the Cocoa related issues, but the CD issues may not be as straightforward. In particular, when running the second version of the second project, you may get the error: &#8220;missing source managed object model&#8221;. I only found a couple of references to this error when googling, but because there were so few, and I double and triple checked my code against the book, I assumed the problem must be me. As usual, it was. The simple answer is this: Don&#8217;t give your project the exact same name as Zarra does in his book, if you want to also run the projects included in the book&#8217;s source code. There is a hash generated when a Core Data project is run and it&#8217;s stored in the xml file in the Application Support folder. This hash is used when running a CD project and when migrating a CD data store to a new version. If you run Zarra&#8217;s code and the project has the same name, the hash will get changed. If you then attempt the second version of the project with this changed hash, you&#8217;ll get the title of this post as an error. If you do get the error, delete the xml file, run the first version of the project and recreate the data. Now you should be able to run the second version of the project and your data will be migrated as expected. I&#8217;m sure there are more details that I&#8217;m not aware of yet, but this should get you passed this error. I&#8217;ll continue to post as I work through the book, so feel free to check in from time to time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spikesoft.net/blog/?feed=rss2&#038;p=17</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mutually exclusive NSTableView selections</title>
		<link>http://www.spikesoft.net/blog/?p=1</link>
		<comments>http://www.spikesoft.net/blog/?p=1#comments</comments>
		<pubDate>Sun, 10 Jan 2010 17:10:02 +0000</pubDate>
		<dc:creator>Lorenzo</dc:creator>
				<category><![CDATA[NSTableView]]></category>
		<category><![CDATA[nstableview delegate]]></category>
		<category><![CDATA[nstableview notifications]]></category>
		<category><![CDATA[selection]]></category>

		<guid isPermaLink="false">http://www.spikesoft.net/blog/?p=1</guid>
		<description><![CDATA[While developing Weather Vane, I ran into a problem trying to bind a selection from one of two different tables to a location ivar, which can only reflect the value of one selection at a time. In Weather Vane&#8217;s preferences, when a user does a search for a city, multiple results may be returned, some [...]]]></description>
			<content:encoded><![CDATA[<p>While developing <a href="http://www.spikesoft.net/downloads.php#wv">Weather Vane</a>, I ran into a problem trying to bind a selection from one of two different tables to a location ivar, which can only reflect the value of one selection at a time. In Weather Vane&#8217;s preferences, when a user does a search for a city, multiple results may be returned, some international and some US. International and US results are placed in separate tables. If the user selects a US city, the ivar is updated as expected. If the user then selects an international city, the ivar is again updated, but if the user then reselects the original US city, the ivar is not updated. The reason had to do with how and when the NSTableViewSelectionDidChangeNotification is sent.</p>
<p>When the initial selection was made in the US table, the notification is sent, the same occurs when a selection is made in the international table. But when the same selection is made again in the US table, the original selection is still valid even though the US table lost focus when the international selection was made, so reselecting it does not trigger an NSTableViewSelectionDidChangeNotification.</p>
<p>When the NSTableViewSelectionDidChangeNotification is sent, an NSTableView delegate method is invoked (if you&#8217;ve chosen to be notified of selection changes, or set some class in your project as the NSTableView&#8217;s delegate):</p>
<p>- (void)tableViewSelectionDidChange:(NSNotification *)aNotification</p>
<p>My initial attempt to resolve the selection problem tried to handle the problem in this method by deselecting everything in the &#8216;other&#8217; table (the one losing focus), but what I found is that this led to additional notifications being sent. Every selection triggers a notification AND every deselection triggers a notification as well. One could easily end up with looping notifications this way, which is a problem.</p>
<p>I have a small project which illustrates the problem. You can download it <a href="http://www.spikesoft.net/downloads/mutex_tables.zip">here</a>. (Please note: Although I called the project mutex_tables, one should not confuse this with locks of any sort). The name was determined from the mutually exclusive nature of the tables.</p>
<p>When the tables are initially populated, things look like this:<br />
<img src="http://www.spikesoft.net/blog_images/iss.jpg" alt="Initially populated tables" /></p>
<p>Once a selection is made, an NSTextField below the tables has its stringValue set (like my location ivar).<br />
<img src="http://www.spikesoft.net/blog_images/1ss.jpg" alt="Initial selection made, NSTextField updated." /></p>
<p>After making a selection in the second table, the NSTextField is also updated:<br />
<img src="http://www.spikesoft.net/blog_images/2ss.jpg" alt="Second selection made, NSTextField updated." /></p>
<p>Notice, the selection in the first table, although grayed out since the table has lost focus, is still highlighted.</p>
<p>Now, if we select the same item in the first table, nothing happens. Since technically, there is no change in the selection, the notification is not fired and the text field is not updated.<br />
<img src="http://www.spikesoft.net/blog_images/3ss.jpg" alt="Original selection made, NSTextField NOT updated." />.</p>
<p>The solution I found is to use another delegate method,</p>
<p>-(BOOL)tableView:(NSTableView*)aTableView shouldSelectRow:(NSInteger)rowIndex</p>
<p>to handle the deselection in the &#8216;other&#8217; (unfocused) table.</p>
<p>When called, a selection is about to made in one of the tables. What I do then is deselect everything in the &#8216;other&#8217; table. Now, in tableViewSelectionDidChange, I can just &#8220;find&#8221; the new selection and update the textfield accordingly. tableViewSelectionDidChange will be called once on the initial selection, and twice thereafter, but never more than twice. Two notifications seem to be unavoidable.</p>
<p>Here&#8217;s how things look now after I implemented the new delegate method:</p>
<p>Initial unselected view:<br />
<img src="http://www.spikesoft.net/blog_images/iss.jpg" alt="Initially populated tables" /></p>
<p>After first selection is made:<br />
<img src="http://www.spikesoft.net/blog_images/1ss.jpg" alt="Initial selection made, NSTextField updated." /></p>
<p>After second selection in the other table is made:<br />
<img src="http://www.spikesoft.net/blog_images/f2ss.jpg" alt="Second selection made, NSTextField updated." /></p>
<p>But now with our newly implemented delegate method in place, reselecting the original item in the first table, things work properly:<br />
<img src="http://www.spikesoft.net/blog_images/f3ss.jpg" alt="Reselect initial item in the first table, NSTextField updated." /></p>
<p>Nothing in the unfocused table is highlighted and as selections are made between the tables, only the current selection in the current table will be highlighted.</p>
<p>Here is my implementation of tableView:shouldSelectRow:</p>
<p>-(BOOL)tableView:(NSTableView*)aTableView shouldSelectRow:(NSInteger)rowIndex{</p>
<p>// Deselecting generates an NSTableViewSelectionDidChangeNotification<br />
// notification.<br />
if (aTableView == self.secondTableView) {<br />
[self.firstTableView deselectAll:self];<br />
}<br />
else {<br />
[self.secondTableView deselectAll:self];<br />
}<br />
return YES;<br />
}</p>
<p>And my tableViewSelectionDidChange<br />
// This will be called once on the initial selection<br />
// twice thereafter.<br />
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification{</p>
<p>NSDictionary * item = nil;<br />
NSUInteger  index;</p>
<p>// Make sure we have the right table and ignore no-selection<br />
if([aNotification object] == self.firstTableView &amp;&amp; [self.firstController selectionIndex] != NSNotFound){<br />
index = [self.firstController selectionIndex];<br />
item = [self.firstTableArray objectAtIndex:index];<br />
}<br />
else if([aNotification object] == self.secondTableView &amp;&amp; [self.secondController selectionIndex] != NSNotFound){<br />
index = [self.secondController selectionIndex];<br />
item = [self.secondTableArray objectAtIndex:index];<br />
}</p>
<p>// When two notifications are sent, item will be nil on first notification<br />
if (item) {<br />
[self.selectionField setStringValue:[item objectForKey:@"test"]];<br />
}<br />
}</p>
<p>You can download the updated project <a href="http://www.spikesoft.net/downloads/mutex_tables_fixed.zip">here</a>.</p>
<p>By the way, don&#8217;t forget to check the  &#8220;Avoid Empty Selection” box for the associated NSArrayController.</p>
<p>I hope people find this useful. If someone has a better way, please feel free to comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spikesoft.net/blog/?feed=rss2&#038;p=1</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

