NSOutlineView, NSTreeController and itemForPersistentObject...

  • Hello,

    I'm running into yet more problems with
    NSTreeController... It seems that this class is only
    half-finished, but maybe I am wrong. The problem is
    that when you use bindings with an NSOutlineView using
    NSTreeController, the delegate and datasource methods
    do not have direct access to the items held by
    NSTreeController, which seems like madness to me...

    For instance, if you hook up a datasource to an
    NSOutlineView that uses bindings (eg. the one in the
    OutlineEdit Core Data example) and then try to use a
    datasource method such as
    outlineView:persistentObjectForItem:, you will find
    that the "item" object passed in is not the actual
    object, but a proxy object of class
    _NSArrayControllerTreeNode.

    When I was experiencing a similar problem a few days
    ago, Scott Stevenson on this list very helpfully
    pointed out that the only way he knew around this was
    to use an undocumented method, -observedObject.
    Calling this on the item passed into outline view
    datasource and delegate methods does indeed retrieve
    the object.

    However, I am now trying to get my outline view to
    save its state using the datasource methods, and
    whilst I can use -observedObject to get a persistent
    object in outlineView:persistentObjectForItem:, there
    is no way to use this information to restore things in
    outlineView:itemForPersistentObject:, because
    NSTreeController will expect this to return an object
    of type _NSArrayControllerTreeNode - a private API
    class.

    It seems insane that using Core Data and bindings with
    an outline view would prevent you from using any of
    the useful datasource or delegate methods that call
    for direct access to the item, but I cannot find
    anything to solve this.

    If anybody has delved into this, I would be very
    grateful for some pointers.

    Many thanks in advance,
    Keith


    Yahoo! Mail
    Stay connected, organized, and protected. Take the tour:
    http://tour.mail.yahoo.com/mailtour.html
  • Hmm, I'm still having no joy with this... In the hope
    that someone will soon start experimenting with
    NSTreeController and run into the same problems, I've
    described the problem in a little more detail here:

    http://www.cocoadev.com/index.pl?OutlineViewCoreDataBindings

    I've also filed a bug report, as it seems to me that
    NSOutlineView's delegate and datasource methods
    shouldn't be rendered unusable by using
    NSTreeController and bindings...

    If anyone here has played with NSTreeController and
    outine views and managed to get the outline view to
    save its state (and use other datasource/delegate
    methods that use (id)item), I would be really grateful
    if you could point me in the right direction, as I'm
    sure I must be missing something here. At the moment,
    it looks like I'm going to have to abandon
    NSTreeController...

    Many thanks,
    Keith

    --- Keith Blount <keithblount...> wrote:
    > Hello,
    >
    > I'm running into yet more problems with
    > NSTreeController... It seems that this class is only
    > half-finished, but maybe I am wrong. The problem is
    > that when you use bindings with an NSOutlineView
    > using
    > NSTreeController, the delegate and datasource
    > methods
    > do not have direct access to the items held by
    > NSTreeController, which seems like madness to me...
    >
    > For instance, if you hook up a datasource to an
    > NSOutlineView that uses bindings (eg. the one in the
    > OutlineEdit Core Data example) and then try to use a
    > datasource method such as
    > outlineView:persistentObjectForItem:, you will find
    > that the "item" object passed in is not the actual
    > object, but a proxy object of class
    > _NSArrayControllerTreeNode.
    >
    > When I was experiencing a similar problem a few days
    > ago, Scott Stevenson on this list very helpfully
    > pointed out that the only way he knew around this
    > was
    > to use an undocumented method, -observedObject.
    > Calling this on the item passed into outline view
    > datasource and delegate methods does indeed retrieve
    > the object.
    >
    > However, I am now trying to get my outline view to
    > save its state using the datasource methods, and
    > whilst I can use -observedObject to get a persistent
    > object in outlineView:persistentObjectForItem:,
    > there
    > is no way to use this information to restore things
    > in
    > outlineView:itemForPersistentObject:, because
    > NSTreeController will expect this to return an
    > object
    > of type _NSArrayControllerTreeNode - a private API
    > class.
    >
    > It seems insane that using Core Data and bindings
    > with
    > an outline view would prevent you from using any of
    > the useful datasource or delegate methods that call
    > for direct access to the item, but I cannot find
    > anything to solve this.
    >
    > If anybody has delved into this, I would be very
    > grateful for some pointers.
    >
    > Many thanks in advance,
    > Keith
    >
    > __________________________________________________
    > Do You Yahoo!?
    > Tired of spam?  Yahoo! Mail has the best spam
    > protection around
    > http://mail.yahoo.com
    >


    Yahoo! Mail
    Stay connected, organized, and protected. Take the tour:
    http://tour.mail.yahoo.com/mailtour.html
  • Le 8 mai 05 à 15:22, Keith Blount a écrit :
    >
    > If anyone here has played with NSTreeController and
    > outine views and managed to get the outline view to
    > save its state (and use other datasource/delegate
    > methods that use (id)item), I would be really grateful
    > if you could point me in the right direction, as I'm
    > sure I must be missing something here. At the moment,
    > it looks like I'm going to have to abandon
    > NSTreeController...
    >
    > --- Keith Blount <keithblount...> wrote:
    >
    >> Hello,
    >>
    >> For instance, if you hook up a datasource to an
    >> NSOutlineView that uses bindings (eg. the one in the
    >> OutlineEdit Core Data example) and then try to use a
    >> datasource method such as
    >> outlineView:persistentObjectForItem:, you will find
    >> that the "item" object passed in is not the actual
    >> object, but a proxy object of class
    >> _NSArrayControllerTreeNode.
    >>
    >> When I was experiencing a similar problem a few days
    >> ago, Scott Stevenson on this list very helpfully
    >> pointed out that the only way he knew around this
    >> was
    >> to use an undocumented method, -observedObject.
    >> Calling this on the item passed into outline view
    >> datasource and delegate methods does indeed retrieve
    >> the object.
    >>
    >> However, I am now trying to get my outline view to
    >> save its state using the datasource methods, and
    >> whilst I can use -observedObject to get a persistent
    >> object in outlineView:persistentObjectForItem:,
    >> there
    >> is no way to use this information to restore things
    >> in
    >> outlineView:itemForPersistentObject:, because
    >> NSTreeController will expect this to return an
    >> object
    >> of type _NSArrayControllerTreeNode - a private API
    >> class.
    >>

    Dear Keith,

    I'm myself trying to use the combination NSOutlineView
    +NSTreeController, but I'm not so advanced than you are, so my
    comments may be of no help: I apologize in advance. (I have asked
    myself a few questions recently on the list on this subject, but
    didn't get any answer :-(.)

    I tried using -observedObject and indeed it does work well. You can
    silent the compiler warnings by putting these lines in your code:

    @interface NSObject (privateAppkit)

    -(id) observedObject;

    @end

    I have still to understand the complete connection between the
    controller, when an NSTreeController is used, and the ouline view.
    Anyway I use the tree controller also as a delegate, and it seems to
    work perfectly. (I use a derived class implementing some of the
    delegate methods). Apparently no data source is needed when using
    Core Data.

    For the -outlineView:itemForPersistentObject: problem, I have no good
    solution. However, these methods only purpose is to save the expanded/
    collapsed state of the items, right? So did you try to save this
    state into the model, and use the delegate methods -
    outlineViewItemDidCollapse: and similar to keep this state consistent
    with the view?

    Yours,

    Thomas Lachand-Robert
    ********************** <tlr...>
    << Et le chemin est long du projet à la chose. >> Molière, Tartuffe.
  • Keith,

    I'm not quite sure what you're trying to accomplish here..

    When using an outline view with bindings and core data, the tree
    controller bound to your outline view provides the data, not the
    datasource delegate.  Since the default NSManagedObject
    implementation does not have attributes to store the state of outline
    view's nodes (if the node is expanded, if the node has children, if
    it is a leaf node, etc.), this information is stored in a
    NSArrayControllerTreeNode object that is wrapped around your
    NSManagedObject or subclass.

    If you're trying to read or restore the expanded or unexpanded state
    of an outline view's nodes, you'll need to walk each node in the
    outline view, get the corresponding persistent object using
    observedObject, then query or set the nodes state by calling the
    appropriate outline view methods with the node, such as
    isItemExpanded:item, collapseItem:item, expandItem:item, etc.

    Since NSOutlineView is a subclass of NSTableView, you can use
    numberOfRows and itemAtRow:index methods to walk the outline view and
    access it's nodes. You can either create an attribute to store this
    state in your persistent object or store it externally.

    Note: Each Core Data persistent object has an built-in read-only
    "objectID" attribute that can be use to uniquely identify each
    object. You can use this ID as a key to externally store the state of
    each object node in your outline view.

    - Scott

    On May 7, 2005, at 1:06 PM, Keith Blount wrote:

    > Hello,
    >
    > I'm running into yet more problems with
    > NSTreeController... It seems that this class is only
    > half-finished, but maybe I am wrong. The problem is
    > that when you use bindings with an NSOutlineView using
    > NSTreeController, the delegate and datasource methods
    > do not have direct access to the items held by
    > NSTreeController, which seems like madness to me...
    >
    > For instance, if you hook up a datasource to an
    > NSOutlineView that uses bindings (eg. the one in the
    > OutlineEdit Core Data example) and then try to use a
    > datasource method such as
    > outlineView:persistentObjectForItem:, you will find
    > that the "item" object passed in is not the actual
    > object, but a proxy object of class
    > _NSArrayControllerTreeNode.
    >
    > When I was experiencing a similar problem a few days
    > ago, Scott Stevenson on this list very helpfully
    > pointed out that the only way he knew around this was
    > to use an undocumented method, -observedObject.
    > Calling this on the item passed into outline view
    > datasource and delegate methods does indeed retrieve
    > the object.
    >
    > However, I am now trying to get my outline view to
    > save its state using the datasource methods, and
    > whilst I can use -observedObject to get a persistent
    > object in outlineView:persistentObjectForItem:, there
    > is no way to use this information to restore things in
    > outlineView:itemForPersistentObject:, because
    > NSTreeController will expect this to return an object
    > of type _NSArrayControllerTreeNode - a private API
    > class.
    >
    > It seems insane that using Core Data and bindings with
    > an outline view would prevent you from using any of
    > the useful datasource or delegate methods that call
    > for direct access to the item, but I cannot find
    > anything to solve this.
    >
    > If anybody has delved into this, I would be very
    > grateful for some pointers.
    >
    > Many thanks in advance,
    > Keith
    >
    >
    >
    > Yahoo! Mail
    > Stay connected, organized, and protected. Take the tour:
    > http://tour.mail.yahoo.com/mailtour.html
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/pixel%
    > 40pixelfreak.net
    >
    > This email sent to <pixel...>
    >
    >
    >

    - - -
    :: <pixel...>
    :: http://www.pixelfreak.net
    - - -
  • Many thanks to you both for your replies. Surely this
    is a lot of extra coding which could be avoided if the
    datasource and delegate methods worked "correctly"? To
    step through all of this just to save the state of an
    outline view when you could just use a couple of lines
    of code using the datasource methods seems to defeat
    the "less code" philosophy of bindings... And even
    going this route, you have to use -observedObject,
    which is a hack because it is a private method.

    Just because you use bindings, you should surely still
    be able to use the datasource and delegate methods?
    When using bindings with NSTableView through
    NSArrayController, you can still use datasource and
    delegate methods to provide drag'n'drop and persistent
    state-saving functionality, so why should this be so
    difficult with NSOutlineView? I still feel that there
    should be a simpler solution, but it looks as though I
    will have to go the route you suggest...

    I think I need to play with this a bit more - maybe it
    is just the Core Data part that is throwing me as I am
    so new to it having only last week got my hands on
    Tiger.

    Many thanks again,
    Keith

    --- Scott Ahten <pixel...> wrote:

    > Keith,
    >
    > I'm not quite sure what you're trying to accomplish
    > here..
    >
    > When using an outline view with bindings and core
    > data, the tree
    > controller bound to your outline view provides the
    > data, not the
    > datasource delegate.  Since the default
    > NSManagedObject
    > implementation does not have attributes to store the
    > state of outline
    > view's nodes (if the node is expanded, if the node
    > has children, if
    > it is a leaf node, etc.), this information is stored
    > in a
    > NSArrayControllerTreeNode object that is wrapped
    > around your
    > NSManagedObject or subclass.
    >
    > If you're trying to read or restore the expanded or
    > unexpanded state
    > of an outline view's nodes, you'll need to walk each
    > node in the
    > outline view, get the corresponding persistent
    > object using
    > observedObject, then query or set the nodes state by
    > calling the
    > appropriate outline view methods with the node, such
    > as
    > isItemExpanded:item, collapseItem:item,
    > expandItem:item, etc.
    >
    > Since NSOutlineView is a subclass of NSTableView,
    > you can use
    > numberOfRows and itemAtRow:index methods to walk the
    > outline view and
    > access it's nodes. You can either create an
    > attribute to store this
    > state in your persistent object or store it
    > externally.
    >
    > Note: Each Core Data persistent object has an
    > built-in read-only
    > "objectID" attribute that can be use to uniquely
    > identify each
    > object. You can use this ID as a key to externally
    > store the state of
    > each object node in your outline view.
    >
    > - Scott
    >
    > On May 7, 2005, at 1:06 PM, Keith Blount wrote:
    >
    >> Hello,
    >>
    >> I'm running into yet more problems with
    >> NSTreeController... It seems that this class is
    > only
    >> half-finished, but maybe I am wrong. The problem
    > is
    >> that when you use bindings with an NSOutlineView
    > using
    >> NSTreeController, the delegate and datasource
    > methods
    >> do not have direct access to the items held by
    >> NSTreeController, which seems like madness to
    > me...
    >>
    >> For instance, if you hook up a datasource to an
    >> NSOutlineView that uses bindings (eg. the one in
    > the
    >> OutlineEdit Core Data example) and then try to use
    > a
    >> datasource method such as
    >> outlineView:persistentObjectForItem:, you will
    > find
    >> that the "item" object passed in is not the actual
    >> object, but a proxy object of class
    >> _NSArrayControllerTreeNode.
    >>
    >> When I was experiencing a similar problem a few
    > days
    >> ago, Scott Stevenson on this list very helpfully
    >> pointed out that the only way he knew around this
    > was
    >> to use an undocumented method, -observedObject.
    >> Calling this on the item passed into outline view
    >> datasource and delegate methods does indeed
    > retrieve
    >> the object.
    >>
    >> However, I am now trying to get my outline view to
    >> save its state using the datasource methods, and
    >> whilst I can use -observedObject to get a
    > persistent
    >> object in outlineView:persistentObjectForItem:,
    > there
    >> is no way to use this information to restore
    > things in
    >> outlineView:itemForPersistentObject:, because
    >> NSTreeController will expect this to return an
    > object
    >> of type _NSArrayControllerTreeNode - a private API
    >> class.
    >>
    >> It seems insane that using Core Data and bindings
    > with
    >> an outline view would prevent you from using any
    > of
    >> the useful datasource or delegate methods that
    > call
    >> for direct access to the item, but I cannot find
    >> anything to solve this.
    >>
    >> If anybody has delved into this, I would be very
    >> grateful for some pointers.
    >>
    >> Many thanks in advance,
    >> Keith
    >>
    >>
    >>
    >> Yahoo! Mail
    >> Stay connected, organized, and protected. Take the
    > tour:
    >> http://tour.mail.yahoo.com/mailtour.html
    >>
    >> _______________________________________________
    >> Do not post admin requests to the list. They will
    > be ignored.
    >> Cocoa-dev mailing list
    > (<Cocoa-dev...>)
    >> Help/Unsubscribe/Update your Subscription:
    >>
    >
    http://lists.apple.com/mailman/options/cocoa-dev/pixel%
    >
    >> 40pixelfreak.net
    >>
    >> This email sent to <pixel...>
    >>
    >>
    >>
    >
    > - - -
    > :: <pixel...>
    > :: http://www.pixelfreak.net
    > - - -
    >
    >


    Discover Yahoo!
    Find restaurants, movies, travel and more fun for the weekend. Check it out!
    http://discover.yahoo.com/weekend.html