NSTableView, NSArrayController, NSManagedObjectContext

  • It feels like this has to be an FAQ, but I still can't figure it out...

    I have a one-column NSTableView, with the 'value' binding of the
    column bound to arrangedObjects.someProperty in an NSArrayController.
    The NSArrayController is in "entity" mode and with its
    managedObjectContext binding bound to an NSManagedObjectContext. If I
    add objects to this MOC, they pop up neatly in the NSTableView. So
    far, so good.

    Then I have another NSManagedObjectContext, with the same core data
    stack beneath it. When I add objects to this MOC (on another thread),
    the do _not_ pop up in the NSTableView until I restart my application.
    What exactly do I need to do get these objects into the MOC bound to
    the table view, so that the table view updates correctly?

      -- Ture
  • On Jan 1, 2008, at 4:25 AM, Ture Pålsson wrote:

    > Then I have another NSManagedObjectContext, with the same core data
    > stack beneath it. When I add objects to this MOC (on another thread),
    > the do _not_ pop up in the NSTableView until I restart my application.
    > What exactly do I need to do get these objects into the MOC bound to
    > the table view, so that the table view updates correctly?
    >
    <http://developer.apple.com/documentation/Cocoa/Conceptual/CoreData/Articles
    /cdChangeManagement.html#//apple_ref/doc/uid/TP30001201-DontLinkElementID_1
    8
    >

    mmalc
  • On Jan 1, 2008 6:17 PM, mmalc crawford <mmalc_lists...> wrote:
    >
    > On Jan 1, 2008, at 4:25 AM, Ture Pålsson wrote:
    >
    >> Then I have another NSManagedObjectContext, with the same core data
    >> stack beneath it. When I add objects to this MOC (on another thread),
    >> the do _not_ pop up in the NSTableView until I restart my application.
    >> What exactly do I need to do get these objects into the MOC bound to
    >> the table view, so that the table view updates correctly?
    >>
    > <http://developer.apple.com/documentation/Cocoa/Conceptual/CoreData/Articles/cdChangeManagement.html#//apple_ref/doc/uid/TP30001201-DontLinkElementID_18

    Thank you, I have read that about a gazillion times but I am obviously
    managing to overlook some important bit of it...

    Here's what I do:

    In the thread that adds the objects, I do [moc save: &saveError] every
    now and then.

    I subscribe to NSManagedObjectContextDidSaveNotification. In the
    notification handler, I extract the object ID:s of the inserted
    objects and pass them to a method on the main thread (using
    performSelectorOnMainThread). On the main thread, I loop over the
    objectID:s and... well, what *should* I be doing here? I tried just
    accessing the objects with [moc objectWithID:]. No luck. I tried
    calling [moc refreshObject: mergeChanges:] for the objects I got by
    objectByID. No luck. I tried executing fetch requests for those
    objects. No luck.
  • On Jan 1, 2008, at 12:38 PM, Ture Pålsson wrote:

    > I subscribe to NSManagedObjectContextDidSaveNotification. In the
    > notification handler, I extract the object ID:s of the inserted
    > objects and pass them to a method on the main thread (using
    > performSelectorOnMainThread). On the main thread, I loop over the
    > objectID:s and... well, what *should* I be doing here?

      Have you tried telling your *Array Controller* to -fetch: at this
    point?

    --
    I.S.
  • On Jan 1, 2008, at 9:38 AM, Ture Pålsson wrote:

    > In the thread that adds the objects, I do [moc save: &saveError] every
    > now and then.
    >
    > I subscribe to NSManagedObjectContextDidSaveNotification. In the
    > notification handler, I extract the object ID:s of the inserted
    > objects and pass them to a method on the main thread (using
    > performSelectorOnMainThread). On the main thread, I loop over the
    > objectID:s and... well, what *should* I be doing here? I tried just
    > accessing the objects with [moc objectWithID:]. No luck. I tried
    > calling [moc refreshObject: mergeChanges:] for the objects I got by
    > objectByID. No luck. I tried executing fetch requests for those
    > objects. No luck.
    >
    Are you actually getting back the new objects when you execute the
    fetch?

    Are you sending the array controller a fetch: message?

    mmalc
  • > Have you tried telling your *Array Controller* to -fetch: at this
    > point?

    No. I was under the impression that the NSArrayController would watch
    "its" moc for changes and update automagically (because the
    "automatically prepares content" flag is set for the controller). Is
    this not the case?
  • On Jan 1, 2008, at 1:02 PM, Ture Pålsson wrote:

    >> Have you tried telling your *Array Controller* to -fetch: at this
    >> point?
    >
    > No. I was under the impression that the NSArrayController would watch
    > "its" moc for changes and update automagically (because the
    > "automatically prepares content" flag is set for the controller). Is
    > this not the case?

      Hmm ... the documentation says of that flag:

    "Sets whether the receiver automatically creates and inserts new
    content objects automatically when loading from a nib file."

      ... and ...

    "If ... a managed object context is set, the initial content is
    fetched from the managed object context using the current fetch
    predicate."

      Doesn't sound like it works the way you described to me ... ;-)

    --
    I.S.
  • On Jan 1, 2008 7:24 PM, I. Savant <idiotsavant2005...> wrote:
    >
    > On Jan 1, 2008, at 1:02 PM, Ture Pålsson wrote:
    >
    >>> Have you tried telling your *Array Controller* to -fetch: at this
    >>> point?
    >>
    >> No. I was under the impression that the NSArrayController would watch
    >> "its" moc for changes and update automagically (because the
    >> "automatically prepares content" flag is set for the controller). Is
    >> this not the case?
    >
    > Hmm ... the documentation says of that flag:
    >
    > "Sets whether the receiver automatically creates and inserts new
    > content objects automatically when loading from a nib file."
    >
    > ... and ...
    >
    > "If ... a managed object context is set, the initial content is
    > fetched from the managed object context using the current fetch
    > predicate."
    >
    > Doesn't sound like it works the way you described to me ... ;-)

    True. Then again, the docs also say "If the controller's content is
    fetched automatically, set the "Automatically prepares content" switch
    for the controller in the Attributes inspector in Interface Builder
    (see also automaticallyPreparesContent). Doing so means that the
    controller tracks inserts into and deletions from its managed object
    context for its entity." That last sentence is what lead me to believe
    what I believed. Maybe I should not pay too much attention to such
    peripheral parts of the docs as "troubleshooting". :-)

    Oh well, assuming that I do need to call refresh: on the
    NSArrayController, how does one solve this architecturally? One of the
    nice things about using KVO in general and Cocoa Bindings in
    particular, is that models do not need to know that the NSViews and
    NSControllers and stuff even exists. Now, if I need to nudge the
    NSControllers to make them update themselves, that means that the
    model objects need to know about the controllers. Is this not a bit
    ugly, or is there some way around this that I have not realized?
  • On Jan 1, 2008, at 10:34 AM, Ture Pålsson wrote:

    > Doing so means that the controller tracks inserts into and deletions
    > from its managed object
    > context for its entity."
    >
    The key word there is "its".  You're inserting into another context.

    > Oh well, assuming that I do need to call refresh: on the
    > NSArrayController, how does one solve this architecturally?
    >
    Exactly as you appear to have already done.  Register for change
    notifications from the second context and update the array controller
    on receipt.

    > Now, if I need to nudge the NSControllers to make them update
    > themselves, that means that the
    > model objects need to know about the controllers.
    >
    I'm not sure how that follows?  The model objects don't need to know
    about the controllers -- controllers know about other controllers.
    Managed objects themselves don't need to know...

    mmalc
  • On Jan 1, 2008 7:49 PM, mmalc crawford <mmalc_lists...> wrote:
    >
    > On Jan 1, 2008, at 10:34 AM, Ture Pålsson wrote:
    >
    >> Doing so means that the controller tracks inserts into and deletions
    >> from its managed object
    >> context for its entity."
    >>
    > The key word there is "its".  You're inserting into another context.

    Ah. Thanks for pointing that out.

    >> Now, if I need to nudge the NSControllers to make them update
    >> themselves, that means that the
    >> model objects need to know about the controllers.
    >>
    > I'm not sure how that follows?  The model objects don't need to know
    > about the controllers -- controllers know about other controllers.
    > Managed objects themselves don't need to know...

    Ok, let me rephrase that a bit. :-) I'm still a beginner with Cocoa,
    but so far I have always managed to keep my actual Objective-C code
    (as opposed to NIB files) completely free from references to NSViews
    and NSControllers. My ObjC code exposes stuff using KVC, and the
    objects in the NIBs watch this stuff and do their magic. Now I
    suddenly need do call methods in an NSController, meaning that I need
    to have a reference (probably in the form of an IBOutlet) to this
    controller somewhere. This is what put me off a bit.
  • On Jan 1, 2008, at 2:22 PM, Ture Pålsson wrote:

    > Now I suddenly need do call methods in an NSController, meaning that
    > I need
    > to have a reference (probably in the form of an IBOutlet) to this
    > controller somewhere. This is what put me off a bit.

      Bindings and Core Data don't do everything for you. :-) Just a few
    days ago, mmalc (quite correctly) said, "sometimes you just need to
    write some code".

      In this case, you're doing something outside your array
    controller's purview, so you need to tell it to -fetch: which means
    sending it a message. This in turn means (in your situation) an outlet
    to the array controller in your nib. This is perfectly normal (in
    fact, it's damned near impossible to avoid :-D).

      Take-home message: Don't feel you're doing something 'wrong' or
    'dirty' ... you're on the right track with an outlet.

    --
    I.S.
  • On Jan 1, 2008, at 11:22 AM, Ture Pålsson wrote:

    > Now I suddenly need do call methods in an NSController, meaning that
    > I need
    > to have a reference (probably in the form of an IBOutlet) to this
    > controller somewhere
    >
    Yes, that's perfectly reasonable.

    Or if for some reason you really want to avoid that (and to reiterate,
    there's no need to do so, it's standard Cocoa architecture), you could
    create an NSArrayController subclass that registers for save
    notifications from the other managed object context and updates itself
    in response (depending on your application architecture, it may be
    that you'll need an outlet from the array controller to, say, the
    document object to get the other MOC).

    mmalc
  • On Jan 1, 2008 8:28 PM, I. Savant <idiotsavant2005...> wrote:

    > Bindings and Core Data don't do everything for you. :-) Just a few
    > days ago, mmalc (quite correctly) said, "sometimes you just need to
    > write some code".

    What, we've been hearing about the end of writing code ever since the
    first FORTRAN compilers and they _still_ haven't got it in place?! :-)

    Many thanks to you and mmalc for your help! I'll go and make myself
    some IBOutlets now. :-)

      -- Ture
previous month january 2008 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today