re: CoreData Application not seeing up-to-date information after store updated

  • Andrew,

    > I use [NSManagedObjectContext refreshObject:parentObject
    > mergeChanges:YES] in App A when the notification that the store has
    > been updated is received. I've also tried using the same message with
    > a mergeChanges:NO to turn the objects back into a fault - to no avail.
    >
    > If I quit and relaunch App A then the parent ->  child (and inverse)
    > relationships match exactly what was set in App B.
    >
    > Can anyone give me some suggestions of other ways to refresh the
    > relationships in the parent object in App A ? Is there something else
    > I need to do besides using the refreshObject message ?

    If we were to model the relationship, we'd get something like:

    NSManagedObjectContext <<-> Application <<->> Database

    (App can have multiple contexts, apps can use multiple databases,
    databases can be in use by multiple apps)

    The piece that isn't apparent (although pretty such I've covered this
    in the archives) is the caching that goes on beneath the
    NSPersistentStoreCoordinator.

    MOC <<-> PSC <<-> Application <<->> Database

    -refreshObject:mergeChanges: basically clears/refresh at the level of
    the MOC.  If the PSC has some of the data you care about cached, then
    when the data is viewed again, you'll still see the old cached data.

    For your scenario, the easiest thing to do is, before refreshing,
    execute a fetch request to grab the parent and set the keypaths to
    prefetch the children.  Fetch requests always bring the most recent
    data from the database into memory (cached within the PSC).  This can
    be expensive, as it means a fetch request always performs I/O.
    Mitigating the expense is the cache used by faulting, and that's
    (probably) why you're seeing stale data.

    You can also use the MOC's staleness interval to solve this problem
    more broadly to prevent cached data from being reused after a certain
    length of time.
    --

    terminally curious,

    -Ben

    __________________________________________________________________________
    Ben Trumbull
    <trumbull...>                            Development Technologies
    (408) 974-5790                                      Core Data
    Change is the Epitome of Hope.                      Apple, Inc.
  • On Nov 13, 2007, at 11:56 PM, Ben Trumbull wrote:

    >
    >
    > The piece that isn't apparent (although pretty such I've covered
    > this in the archives) is the caching that goes on beneath the
    > NSPersistentStoreCoordinator.
    >
    > MOC <<-> PSC <<-> Application <<->> Database
    >
    > -refreshObject:mergeChanges: basically clears/refresh at the level
    > of the MOC.  If the PSC has some of the data you care about cached,
    > then when the data is viewed again, you'll still see the old cached
    > data.
    >
    > For your scenario, the easiest thing to do is, before refreshing,
    > execute a fetch request to grab the parent and set the keypaths to
    > prefetch the children.  Fetch requests always bring the most recent
    > data from the database into memory (cached within the PSC).  This
    > can be expensive, as it means a fetch request always performs I/O.
    > Mitigating the expense is the cache used by faulting, and that's
    > (probably) why you're seeing stale data.
    >
    > You can also use the MOC's staleness interval to solve this problem
    > more broadly to prevent cached data from being reused after a
    > certain length of time.

    I found the stalenessInterval in the docs shortly before getting your
    message and tried it out by setting it to something really small
    before I do any fetches and then resetting it back again after works
    fine. However this seems like rather large hammer to crack a small
    nut  so I switched and investigated the
    setRelationshipKeyPathsForPrefetching method. What I found was that I
    had to do the following :

            NSFetchRequest *aFetchRequest = [parentArrayController
    defaultFetchRequest];
            [aFetchRequest setRelationshipKeyPathsForPrefetching:[NSArray
    arrayWithObject:@"children"]];
            NSArray *array = [[[NSApp delegate] managedObjectContext]
    executeFetchRequest:aFetchRequest error:&error];
            for (Parent *aParent in array)
            {
              [[[NSApp delegate] managedObjectContext]
    refreshObject:aParent mergeChanges:YES];
            }

    For things to work out correctly such that a subsequent fetch on the
    parent objects gives back a valid set for the children relationship.
    Does this still seem appropriate ? This code is executed when the App
    is notified that the store has been updated. It's not easy to execute
    something like this before the update occurs - but does that really
    matter ?

    Andrew 8-)
previous month november 2007 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    
Go to today