Why does my core data object not show up using fetch requests between related objects that were created in the same session?

StackOverflow https://stackoverflow.com/questions/10531605

Question

This is a really weird situation which I have been battling to resolve over the last couple of days.

I have a Card entity with a To-Many relationship on a Transaction entity. I am also using Magical Record to remove the boilerplate code around managing my data store.

My problem occurs in the following order:

  1. Create a Card object
  2. Then create a Transaction object in another view
  3. When I inspect the transaction count with [card.transactions count] I get 1 as the size
  4. However, if I perform a fetch request using the same context the transaction is not there. My predicate looks like this:

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"card == %@ && deleted == 0", card];

So logic says that I am perhaps not saving the context after saving the transaction, but the weird thing is that if I quit the app and then rerun it, the transaction is there. Steps 1-4 work perfectly too if I create the card, quit the app and then run the app and add a transaction. Then my save transaction code works fine.

So my question is, why aren't my objects showing up using fetch requests on a newly created parent object, where "newly created" means that it was created in the same session as the child object.

My code for creating the card looks like this:

GYCard *card = [GYCard MR_createInContext:[NSManagedObjectContext MR_defaultContext]];
[[NSManagedObjectContext MR_defaultContext] MR_save];

Then when I save the transaction my code looks like this:

NSManagedObjectContext *localContext = [NSManagedObjectContext MR_defaultContext];
NSNumber *transactionAmount = [self.numberFormatter numberFromString:self.transactionAmountLabel.text];
GYTransaction *transaction = [GYTransaction MR_createInContext:localContext];
transaction.amount = transactionAmount;
transaction.deleted = [NSNumber numberWithBool:NO];
transaction.card = self.card;
[localContext MR_save];

The code that is not working is this:

+ (int) countTransactions:(GYCard *) card {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"card == %@ && deleted == 0", card];
    return [GYTransaction MR_countOfEntitiesWithPredicate:predicate inContext:[NSManagedObjectContext MR_defaultContext]];
}

The countTransactions always returns 0 if the card was created in the same session. But it works 100% if I quit the app and relaunch. It also works for adding any new transactions to the card after quitting and relaunching the app.

Was it helpful?

Solution

This appears to be a Magical Record issue. I was using the 2.0 beta branch of Magical Record and after reverting to the tagged version:1.8.3 the issue disappears. So 2.0 seems to be the culprit. It would still be interesting to know however, why version 2.0 is causing this problem.

I would strongly advise anybody who is using Magical Record to avoid the 2.0 branch until it comes out of beta.

Update: After further investigation what the 2.0 beta of Magical Record was doing was generating 2 save notifications for 1 save, this led to my app inadvertently have 2 versions of the card. This resulted in causing the transaction that I was logging to be logged on the first card but the second card obviously did not have a transaction on it. My fetch request was then fetching the second card and returning zero transactions. Quitting and restarting the app then made my app load the correct transaction from the data store and thus worked as expected.

OTHER TIPS

This could be related to the includesPendingChanges property on NSFetchRequest. However the default for this is YES which means any unsaved changes should be included in any queries.

I'm not sure what the MR_ methods are doing under the hood, but the setIncludesPendingChanges: documentation states:

Special Considerations

A value of YES is not supported in conjunction with the result type NSDictionaryResultType, including calculation of aggregate results (such as max and min). For dictionaries, the array returned from the fetch reflects the current state in the persistent store, and does not take into account any pending changes, insertions, or deletions in the context.

So I would make sure the MR_countOfEntitiesWithPredicate method is not doing anything funky. Maybe try calling the standard - (NSUInteger)countForFetchRequest:(NSFetchRequest *)request error: (NSError **)error method on your context and see what that returns.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top