September 09, 2005

NSOutlineView, reloading items, and the expansion state

NSOutlineView requires all of the items in it to be pointer unique. If they are not, strange things happen. However, they can be equal (meaning [NSObject isEqual] may return YES).

However, there is a small exception to that rule. If you do a reload, the expansion state of items will be preserved. This expansion state is done by placing the current expanded items into an NSMutableSet. After a reload happens, if an item is in that set it is shown expanded.

What does this mean? Well, to see if an item should be expanded or not, it is looked up in the set. This is done via the item's hashcode and an isEqual comparision. Ahh ha! NSOutlineView is doing some non-pointer unique things here. This means you could potentially switch out items during a reload, and they would still appear expanded after the reload (as long as they have the same hashcode and are isEqual). Another nasty side effect: any items which mutate their hashtable will not appear expanded after a reload! For instance, if you modify an NSDictionary, its hash code will change. Take this point into consideration: the objects you put into an NSOutlineView are NSMutableDictionaries. You do a reload, and after the reload you add a child to one of the items via a key in the NSDictionary. Therefore, the NSMutableDictionary now has a different hashcode, and it will no longer appear expanded! The easy way to work around this is to use a non-mutable object in the outlineview (such as your own object, which might have a dictionary inside of it to keep track of things). Just a neat tip, for those who care or run into this.

Posted by corbin at 03:54 PM | Comments (0)

August 12, 2005

Sharing your mouse, keyboard and pasteboard with several Macs (or PC's)

Like many people, I have several computers at work that I frequently switch among:

Corbinsofficecomputers

I recently started using Synergy to share my mouse, keyboard and pasteboard among my main work G5 and my home Powerbook. It is pretty cool, and fairly easy to setup. Once I pop into work, I run a little script to start the client on my PowerBook:


#!/bin/sh
prog=(/Users/corbin/synergy/synergyc neeb.apple.com)

### Stop any currently running Synergy client
killall ${prog[0]##*/}

### Start the new client
exec “${prog[@]}”

I set this to be always opened with Console, and I manually double click on it when I want to start the synergy client.

Read the documentation for the exact way to set it up..once you have it running, it is very cool!

Posted by corbin at 02:19 PM | Comments (8)

August 01, 2005

Using Xcode to become a faster programmer

You can utilize some of Xcode's cool features to become a faster Mac OS X programmer. Here are some things which you may not know:

1. Use Code Completion (Code Sense). However, the default keyboard shortcut is lame. Go to the Xcode preferences, Key Bindings:

Keybindingsinxcode

and change the Code Sense Completion List binding to be Ctrl-Space (I use Option-Space, but really it is the ctrl-key, because I like to swap my ctrl and option keys):

Xcodecodesensebinding

While you are there, set the Code Sense Select Next Placeholder to be Ctrl-/ (that is control forward slash, and again, I have mine set to be option-/ because I swap my keys):
Codesensenextcompletion

2. Now that you have it properly setup, use it! Here is how you should be using it:

You want to call a particular method in your current class (self). Type the first few characters:

Usingcodesense1

Hit Ctrl-Space to bring up the Code Sense window:

Usingcodesense2

Type a few more characters to narrow down what you want, and arrow key down to select the signature you want to use:

Usingcodesense3

Hit enter to add the template into your source code:

Usingcodesense4

Fill in the first parameter:

Usingcodesense5

Then, hit Ctrl-/ to go the next completion item and highlight it:

Usingcodesense6

Repeat with more Ctrl-/ commands until you are done.

3. Congratulations! You are now a faster programmer.

--corbin

Posted by corbin at 10:44 PM | Comments (2)

June 22, 2005

Fixing the annoying focus stealing habit of Safari RSS feeds

Safari RSS support is way cool. Except for the fact that after a page has loaded, the search field receives focus, causing the space bar to not scroll down a page at a time. I wanted to fix this...but how?

Well, I browsed to an RSS feed and viewed the source in Safari. I noticed this line:

<script language=JavaScript src=“feed:///__rsrc__/Articles.js”>

So, Safari uses some internal file called Articles.js. Now, where is it?

Well, I dropped down to a command prompt in Console, logged in as root (su'd) and typed:

nibroc:/Users/corbin/Desktop root# fs_usage -w -f filesys Safari | grep Articles.js

console

Okay! It is in some framework directory, A/Resources/Articles.js. But which one? Again, a simple command can reveal the secrets:

nibroc:/Users/corbin/Desktop root# otool -L /Applications/Safari.app/Contents/MacOS/Safari

Picture 4

Okay, it probably is SyndicationUI.framework or WebKit.framework. Which one?

nibroc:/Users/corbin/Desktop root# ls /System/Library/PrivateFrameworks/SyndicationUI.framework/Versions/A/Resources/

Picture 6

Gotcha!
vi that file, search for focus, and comment out the offending line:

Picture 7

And we are done! No more focus stealing...

Posted by corbin at 09:54 AM | Comments (3)

June 20, 2005

Debugging OCTest bundles

To debug OCTest bundles:

1. Add a new executable to your Xcode project pointing it to "otest" at /Developer/Tools/otest
2. Double click on the executable, and add two run params (requires Xcode 2.1):
  a. -SenTest Self
  b. $(BUILT_PRODUCTS_DIR)/YourBundleName.octest

This makes it REALLY easy to debug OCUnit tests. You can debug an individual test suite with:

  -SenTest UnitTestClassName

or an individual test case with:

  -SenTest UnitTestClassName/testMethodName

For instance, here is what one of my arguments looks like in Xcode 2.1:


Unittestingoptionsshot


I can easily test/debug all tests, or an individual test by turning on/off arguments. Note that it doesn't have the "$(BUILT_PRODUCTS_DIR)/YourBundleName.octest" option because this is for an executable, not a bundle.

Posted by corbin at 03:00 PM | Comments (0)

June 19, 2005

Tiger and the keyboard

Okay, one of the coolest Tiger enhancements has to do with keyboard shortcuts. The "really smart" Human Interface people at Apple figured out some stuff that bothered me in Panther. The main one that I like is "move focus to the menu bar". Turn on this shortcut in the "keyboard and mouse" section of System Preferences. By default it is set to Ctrl-F2, but i changed it to Cmd-F2 because it is easier to type.

First, how does it work?
Well, you type "Ctrl-F2" (Cmd-F2 in my case), and the Apple menu item has focus. Begin typing, and "type to select" matches what you typed. Way cool! Hit Enter to "drop down" a menu item, and then you can begin typing again to select a sub menu item. It took me a while to realize it is doing a "type-to-select" based on the name, and not "type the first letter to select" (which is the way it works on Windows, but the Apple way is MUCH smarter).

So, what is better about it in Tiger?
Well, in Panther, the apple menu was initially dropped down -- this means, there was no way of type-to-selecting a menu on the top level. Now, I use this feature ALL THE TIME! It is a great speed improvement for touch-typists who don't like using the mouse all that much. For example, in most apps I can type this sequence: "Cmd-F2 F ENTER O" and the "open recent" menu will be open. It is GREAT! Use it. It will save you some time.

Posted by corbin at 02:24 PM | Comments (0)