| Tracing message sends in Objective-C |
[Oct. 30th, 2005|10:05 pm] |
So now I'm trying to get bindings working when I put my NSCell subclass in a table column. It appears, for the standard NSCell subclasses, that NSTableColumn looks at the subclass's exposed bindings and re-exposes them on itself. However, it's not doing that for my NSCell subclass's bindings.
So, I want to trace the messages that are flying around inside Interface Builder to see if I can figure out how NSTableColumn decides what bindings to expose. Ideally I'd have a little dynamic library with a logging version of objc_msgSend and I could get Interface Builder to run using that. I don't have that (yet). I found this old Usenet post from a NeXT engineer showing how to trace objc_msgSend using GDB. That will be much slower than smashing in a logging version of objc_msgSend, but it's better than nothing.
Of course, the GDB command in that Usenet post is for NEXTSTEP running on Intel. It'll probably work on MacOS X running on Intel, but my Powerbook has a PowerPC processor. Also, Apple introduced a new message-send function in Tiger, so you have to set two breakpoints. These commands work on MacOS X on PowerPC:
b objc_msgSend
comm
silent
printf "%c[%s %s]\n", $r3&&((id)$r3)->isa->info&2?'+':'-', $r3?((id)$r3)->isa->name:"nil", $r4
cont
end
b objc_msgSend_rtp
comm
silent
printf "%c[%s %s]\n", $r3&&((id)$r3)->isa->info&2?'+':'-', $r3?((id)$r3)->isa->name:"nil", $r4
cont
end Here's some sample output from GDB, tracing the first few messages sent in -[NSObject exposedBindings]:
-[NSTableColumn _bindingAdaptor]
+[NSBinder binderClassesForObject:]
+[NSBinder _allBinderClasses]
+[NSDisplayPatternTitleBinder isUsableWithObject:]
+[NSBox self]
-[NSTableColumn isKindOfClass:]
+[NSWindow self]
-[NSTableColumn isKindOfClass:]
+[NSWindowTemplate self]
-[NSTableColumn isKindOfClass:]
+[NSTableBinder isUsableWithObject:]
+[NSTableView self]
-[NSTableColumn isKindOfClass:]
+[NSObjectParameterBinder isUsableWithObject:]
+[NSObjectParameterBinder binderClassesSuperseded]
+[NSArray array]
+[NSArray allocWithZone:] |
|
|
| Dragging an NSCell subclass from an Interface Builder palette |
[Oct. 30th, 2005|05:18 am] |
If you've got your own NSCell subclass that you want to put on an Interface Builder palette, you'll probably think that you need to call -[IBPalette associateObject:ofType:withView:] using IBCellPboardType as the type. This doesn't work. It turns out you need to use IBTableColumnPboardType. I don't know what IBCellPboardType is for.
Also, IB will send -[NSCell setObjectValue:] to your cell to fill in the dummy values in puts it tables in design mode. So you have to be able to accept the values it sends (probably of type NSNumber and/or NSString), even if your cell doesn't normally accept values of those types.
Also, if you want to see how IB's built-in "Data Views" palette (the one with the table view and the cells on it) draws the built-in cells, open up this nib:
/Developer/Applications/Interface Builder.app/Contents/Resources/CocoaFramework.palette/Contents/Resources/IBDataViews.nib
It turns out to be kind of a hack, with two NSTextFields and some appropriate control (NSButton, NSSlider, etc.) on top of each other, nested in a simple NSView. The NSTextFields are set up to overlap, with the bottom one having a black border and the top one having no border and covering the sides of the bottom one.
It's very handy to add a "custom executable" to your IB palette Xcode project, with the executable being "/Developer/Applications/Interface Builder.app". Then you can press Command-R to start IB to test out your palette, or Command-Y to run IB under GDB so you can debug your palette. Be careful not to start IB by some other mechanism (like by double-clicking a nib) if you're going to use this technique, because IB won't start up correctly and (at least for me) Xcode will probably hang. |
|
|
| navigation |
| [ |
viewing |
| |
most recent entries |
] |
| |
|
|