« NSZombie eating my brain! | Main | I think I just ate a Zombie »

NSZombie update

I wonder if I'm using cocoa bindings incorrectly... or maybe there's a bug. Usually when I start to think "maybe there's a bug in somebody else's code," I look for ways in which I'm using that code in weird (wrong) ways. I figure that the pyobjc people are about 7 orders of magnitude better at this than I am.

At least I'm getting closer to isolating the problem. Thanks to rewriting the gui and bindings from scratch last night while building and running a simplified version of the project backend after after each new binding (and thanks to finally having a few hours to work on my little hobbies),here's what I know so far. I'll be making a "proof of bug" concept here sometime today. I'll link to it here and post it on the pyobjc-dev list because the below is utterly confusing to me and I wrote it:

1. A regular pyobjc (not document-based) app with the usual appDelegate stuff involved.
2. A simple (doesn't know about objc) python class we'll call Simple (and pretend it has but one attribute we want, a list called 'ourFriends.'
3. A python class we'll call JSNSSimple that has an instance of Simple as an attribute. JSNSSimple subclasses NSObject. This class is defined in our NIB file as *only* a subclass of NSObject. We're using this class to wrap the functionality of Simple in getters and setters to be KVC complient ala cocoa. We've written friends_(self, friends) and getFriends(self). The constructor of JSNSSimple uses the NibClassBuilder.AutoBaseClass voodoo that allows the python object to get it's superclass from the NIB file.
4. We have an array controller to hold instances of JSNSSimple we'll call simpleArrayController that is also an attribute of our appDelegate.
5. We add and subtract instances of JSNSSimple through the appDelegate like so:
add:
newSimple = JSNSSimple.alloc().init()
self.simpleArrayController.addObject_(newSimple)

subtract:
if len(self.simpleArrayController.arrangedObjects()) > 0:
index = self.simpleArrayController.selectionIndex()
self.simpleArrayController.removeObjectAtArrangedObjectIndex_(index)
6. We add an NSTableView to our gui that is bound to some other KVC complient attribute of each JSNSSimple instance (the contents of the array controller) just to see that we really add and subtract JSNSSimple instances from the array. We find that this works.
7. We add an NSPopubButton to our GUI which we want to fill with our "ourFriends" list so that we can select a friend for one reason or another. We add a cocoa binding to follow each currently selected JSNSSimple instance friend attribute. This breaks. Adding one instance of JSNSSimple to the array works just peachy, but upon adding a second...
8. Somehow, in the pyobjc bridge (or perhaps in the way I'm using it incorrectly...) the pyobjc proxy object, an OC_PythonArray, that corresponds to our 'ourFriends' attribute in in the Simple (I think not JSNSSimple) class gets freed and somehow the binding really wants it to stick around. This causes a retain message to get sent to our OC_PythonArray when it's already been freed... and boom.
9. We pull out the binding that caused this crash and everything is back to OK...

Things I'll try next:
1. Remove the autoBaseClass nib file stuff and do a straight subclass of NSObject
2. Add attributes to the NSObject in interface builder that correspond to the 'ourFriends/friends' gettrs and setters.
3. Take a closer look at the stack trace and perhaps (gdb is our friend) break on the free/deallocation of the OC_PythonArray.
4. Give up and do it "a probably smarter way." The 'ourFriends' attribute of the Simple class can probably be accessed in another way. Perhaps we'll use an array controller for it, too.........

TrackBack

TrackBack URL for this entry:
http://www.jonathansaggau.com/blog/mt-tb.cgi/36

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)