Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSManagedObjectContext doesn't refresh correctly

hi :) I have a similarly issue like in Working with the same NSManagedObjectContext in multiple tabs
background:
My managedObjectContext (further MOC) is initialised in my appDelegate class and passed throught to multiple tabs by
myViewController.managedObjectContext = self.managedObjectContext; or in the init method with self.managedObjectContext = pContext; the flow is: the first view is a simple list of collections. The collections are fetched with a NSFetchedResultsController (myViewController : UITableViewController<NSFetchedResultsControllerDelegate>). By selecting one, you navigate deeper, but still passing this MOC.
In the next controller (detailsViewController) I list up some items of this collection what I can interact with (set switches for instance).
I also have an editingObjectContext:

// DetailsViewController.m
NSManagedObjectContext* editingContext = [[NSManagedObjectContext alloc] init];
[editingContext setPersistentStoreCoordinator:[managedObjectContext persistentStoreCoordinator]];
self.editingObjectContext = editingContext;

Now my issue: because my view has to rotate, I am using the folowing trick:

// DetailsViewController.m
DetailsView *localAct = [[DetailsView alloc] initWithManagedObjectContext:managedObjectContext ... ]
DetailsView *localSen = [[DetailsView alloc] initWithManagedObjectContext:managedObjectContext ... ]

UITableView *localContainerView = [[UITableView alloc] init];
self.containerView = localContainerView;
[localContainerView release];
//[...]
[containerView addSubview:actuatorView];
self.tableView = containerView;

further I have a button to manage this items (which of them shall be shown and which not). This button just reloads the table with a new fetchResult.

// DetailsView.m
- (void) manageItems{
managing = !managing;
[viewController setIsManaging:managing]; // parent
self.fetchedResultsController = nil;

NSError *error = nil;
[[self fetchedResultsController] performFetch:&error];

[self reloadData];
[self updateBarButton];
}

The method for putting the items into the context looks so:

// DetailsViewController.m
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// init + create predicate
NSSet* set = [sen filteredSetUsingPredicate:predicate];
if( [set count] > 0 )
{
    for( Act* act in set )
    {
        [editingObjectContext deleteObject:act];
    }
}
else
{
    Act* act = [NSEntityDescription insertNewObjectForEntityForName:@"Act" inManagedObjectContext:editingObjectContext];

    // do things
}
NSError *error = nil;
[[detailView fetchedResultsController] performFetch:&error];

[self.containerView reloadData];
[detailView reloadData];
}

but after I selected the items in the managed view and clicked save (manageItems), the view doesn't show them :/ i have to switch the tab or to navigate in an other controller (parent or deeper) to actualize it. my ViewWillAppear method:

// DetailsViewController.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
DetailsView *detailView = se ? senView : actView;
// [do uninteresting stuff]
[detailView.fetchedResultsController performFetch:nil];
[self.tableView reloadData];
// [do uninteresting stuff]
}

and viewWillDisapper calls

- (void)saveChanges
{
if( ![editingObjectContext hasChanges] )
    return;

// send save-command to server
}

In an earliert Verison where there was only 1 view it worked and I haven't changed realy much... :/ so I don't understand why the MOC is acting like it does. The "manageItems" part is nearly equal, its just a level deeper in the new version (in the DetailsView instead of the controller) ...

if someone can tell me what I can try (always saving to server when switch between managing and normal isn't a solution because the delay in the response from the server is to high for the refresh, so I have the less to flip the view. Also refreshing the views with self.tableView / detailView / self.containerView refresh brings the same result :/ ).

and a second issue: I can't call the "editingObjectContext save:" method after sending to server, because it's throwing errors and don't save at all to local database.

Error in handleChangeResponse: Error Domain=NSCocoaErrorDomain Code=133020 "The operation couldn’t be completed. (Cocoa error 133020.)" UserInfo=0x4d8bb90 {conflictList=( "NSMergeConflict (0x5a2fac0) for NSManagedObject (0x5a46a80) with objectID '0x5a46420 ' with oldVersion = 7 and newVersion = 8 and old object snapshot = {\n iconName = noicon;\n [...] ;\n} and new cached row = {\n iconName = noicon;\n [...] \n}" )}

if you have questions or need some more code (i.e. of the older version) then just ask ;)

thanks in anticipation :)

like image 312
geo Avatar asked Aug 08 '11 15:08

geo


1 Answers

It seems like I have the solution! Since IOS 5.0 there is a new method for NSManagedObjectContext :

[managedObjectContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];

Found on http://pauloliveira.net/tech/core-data-merging-conflicts
Setting this attribute to the top-level MOC (in my case in the appDelegate) and no-where else! clears my merging problems ;)

like image 132
geo Avatar answered Sep 23 '22 00:09

geo