|
From: Jonathan P. <jp...@dc...> - 2006-02-16 19:36:46
|
On 16 Feb 2006, at 16:28, Yvon Thoraval wrote:
>> How are these methods implemented, and what types of values are
>> the items you are returning? They must be NSObject subclasses, and
>> you must keep a reference to them somewhere - otherwise they will
>> be garbage collected and things will go wrong.
>
> for :
> def outlineView_child_ofItem(aTree, index, bookmark)
> i return a REXML::Element :
> return children[index]
OK, this is the problem. NSOutlineView doesn't retain the object
returned from this method. Since REXML::Element is not derived from
NSObject, the object NSOutlineView sees is a temporary proxy for the
ruby instance. Since the proxy is temporary, NSOutlineView gets
confused because it expects to see the same object later.
Here's a workaround for the moment (until there's a better solution
in RubyCocoa core):
# Define helper class
class OutlineViewProxy < OSX::NSObject
ns_overrides :init
def init(slave)
super_init
@slave = slave
self
end
def slave
ObjectSpace._id2ref(@slave) # used to prevent GC cycle
end
end
# One instance of helper class per plain ruby object being helped
module NSOutlineViewable
def to_nsobj
# This will be released with ruby instance is GC-ed
@__nsoutlineviewproxy ||= OutlineViewProxy.alloc.init(self)
end
end
# Include the helper module in REXML::Element
module REXML
class Element
include NSOutlineViewable
end
end
# Now, in any of your outlineView methods that takes an 'item' argument,
# you must get at the real object by using 'slave' first.
# e.g.,
def outlineView_isItemExpandable(aTree, bookmark)
return bookmark.slave.has_elements?
end
Let me know if that works for you.
Jonathan
|