Archive for June, 2005
Thursday, June 30th, 2005
Some people have asked me how to dynamically change the cell that is displayed for each row in an NSTableView or NSOutlineView. Generally, the same cell is used for each row, but it is possible to use a different cell for each row, if you like. NSTableColumn can change the cell that is used for each row. NSTableView calls -[NSTableColumn dataCellForRow:(int)row] for each row. Now, consider this code:
@interface NSObject (VariableCellColumnDelegate)
- (id)tableColumn:(NSTableColumn *)column inTableView:(NSTableView *)tableView dataCellForRow:(int)row;
@end
@interface VariableCellColumn : NSTableColumn
@end
@implementation VariableCellColumn
- (id)dataCellForRow:(int)row {
id delegate = [[self tableView] delegate];
if ([delegate respondsToSelector:@selector(tableColumn:inTableView:dataCellForRow:)]) {
return [delegate tableColumn:self inTableView:[self tableView] dataCellForRow:row];
} else {
return [super dataCellForRow:row];
}
}
@end
If the delegate simply implements the method:
- (id)tableColumn:(NSTableColumn *)column inTableView:(NSTableView *)tableView dataCellForRow:(int)row;
…you will be able to dynamically change the cells, with very little effort! In IB, you can set the class for the NSTableColumn to be VariableCellColumn (after dragging the header into IB), and you won’t have to do any work of dynamically creating NSTableColumn’s.
Posted in Cocoa, General
|
1 Comment »
Wednesday, June 22nd, 2005
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

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

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/

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

And we are done! No more focus stealing…
Posted in Apple, General
|
Comments Off
Monday, June 20th, 2005
Another old article: 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:

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 June 20, 2005 03:00 PM
Posted in Apple, Cocoa, General
|
Comments Off
Friday, June 17th, 2005
(The original of this I accidentally killed — here is a copy).
If your Cocoa application leaks memory, here is a way to find those leaks!
1) Open your application in Object Alloc
2) Start the process, and check to have retain events:
3) Run to a known state
4) Check "Show since mark"
5) Click "Auto sort"
6) Click the "Current" column header to sort on that automatically
7) Click the Mark button
8) Do the offending memory leak operation (to warm it up)
9) Click Mark again, and repeat the offending memory leak operation
10) Take a look at the Instance Browser, and find your objects that are leaked
11) Pause the app, and in the right hand browser column will be the
allocation events. Double click on them and you can see the stack of
the allocation/retain/release event, and figure out who isn’t "playing
nice" by seeing who should have done a release for a corresponding
alloc/retain/copy
|
Posted in Apple, Cocoa, General
|
Comments Off
Wednesday, June 15th, 2005
At WWDC I was asked how to remove the disclosure triangle in an NSOutlineView. Well, first things first. You can change it with this bit of code in your delegate:
- (void)outlineView:(NSOutlineView *)ov
willDisplayOutlineCell:(NSButtonCell *)cell
forTableColumn:(NSTableColumn *)tableColumn
item:(id)item
{
[cell setImage:[NSImage imageNamed:@“collapsedglyph.tiffâ€]];
[cell setAlternateImage:[NSImage imageNamed:@“expandedglyph.tiffâ€]];
}
If you want to set it to nil, you will have to create an image that is empty.
–corbin
Posted in Apple, Cocoa, General
|
Comments Off
Tuesday, June 14th, 2005
I did some cool rail riding last weekend:
http://www.bluetreesoft.com/wallpapers/wallpapers.cgi/east_cliff?ppp=0
Here’s a snapshot:

I am actually right above the cliff. Check out the other pictures.
Cool, huh! This is what I do in my spare time. Today, after work, I’m doing a mountain unicycle ride at the Soquel Demo forest.
Posted in General
|
Comments Off
Friday, June 10th, 2005
At WWDC, I quickly mentioned how easy it is to add tooltip’s to an NSCell for an NSTableView/NSOutlineView.
Here is a quick snippet of code on how to do this only if the text doesn’t fill up the entire cell:
- (NSString *)tableView:(NSTableView *)tv toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)tc row:(int)row mouseLocation:(NSPoint)mouseLocation {
if ([cell isKindOfClass:[NSTextFieldCell class]]) {
if ([[cell attributedStringValue] size].width > rect->size.width) {
return [cell stringValue];
}
}
return nil;
}
You will obviously have to set the delegate for the tableview to be whatever class implements the above method, and this will only work on Tiger. But, it is REALLY easy to do.
Posted in Apple, Cocoa, General
|
3 Comments »
Friday, June 10th, 2005
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 in Apple, General
|
Comments Off
Friday, June 10th, 2005
Mail has a cool way of making unread messages stand out. It is really easy to do this type of thing with NSTableView/NSOutlineView. Subclass the one you want, and override drawRow. Toss in the code you see below, and it should give a cool highlight on all expandable rows in an NSOutlineView (you will have to modify it to have it work in NSTableView — just remove the call to isExpandable).

- (void)drawRow:(int)row clipRect:(NSRect)clipRect {
if (([self isExpandable:[self itemAtRow:row]]) && (![self isRowSelected:row])) {
// Draw a light-blue “mail like†border around the row, if not selected
NSRect rect = [self rectOfRow:row];
[[[NSColor blueColor] colorWithAlphaComponent:50/255.0] set];
NSBezierPath *path = [NSBezierPath bezierPath];
[path setLineCapStyle:NSRoundLineCapStyle];
[path setLineWidth:rect.size.height - 3];
int rowLevel = [self levelForRow:row];
float x = rect.origin.x + 10.0 + (rowLevel * [self indentationPerLevel]);
float y = rect.origin.y + (rect.size.height / 2.0);
[path moveToPoint:NSMakePoint(x,y)];
[path lineToPoint:NSMakePoint(x + rect.size.width - 2*10.0, y)];
[path stroke];
}
[super drawRow:row clipRect:clipRect];
}
NOTE: use this at your own risk. I think resizing the thing doesn’t quite work.
Posted in Apple, Cocoa, General
|
1 Comment »
|