I have an issue with the fetch of an object after added in a relationship. The first time that i fetch the category, always found, then when i added to the relationship the following categories not found.
The relationship is a Many-To-Many
.
Example:
categoryId = 10
If the several categories has the same id
, categoryId = 10
, not found
NSManagedObjectContext *private = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[private setParentContext:self.model.context];
__block NSError *error = nil;
[private performBlockAndWait:^{
GPDeal *deal = [EKManagedObjectMapper objectFromExternalRepresentation:dic withMapping:[GPDeal objectMapping] inManagedObjectContext:private];
for (NSDictionary *dic in responseObject[@"response"]) {
GPCategory *category;
//The first time always found
if ((category = [GPCategory MR_findFirstByAttribute:@"catId" withValue:dic[@"mainAttribute"] inContext:private])) {
NSLog(@"Found");
[category addDealsObject:deal];
} else {
NSLog(@"Not Found");
}
}
}];
NSError *PrivateError = nil;
if (![private save:&PrivateError]) {
NSLog(@"Unresolved error %@, %@", PrivateError, [PrivateError userInfo]);
abort();
}
if (!error) {
//Save on main moc
[self.model saveWithErrorBlock:^(BOOL success, NSError *error) {
if (!success) {
NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]);
}
}];
} else {
NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]);
}
EDIT:
Solved , I guess my problem was that i forgot to save the main context in the end of each iteration .
NSManagedObjectContext *backgroundMOC = [self.model backgroundMOC:self.model.context];
[backgroundMOC performBlockAndWait:^{
for (NSDictionary *dic in responseObject[@"response"]) {
GPDeal *deal = [EKManagedObjectMapper objectFromExternalRepresentation:dic withMapping:[GPDeal objectMapping] inManagedObjectContext:backgroundMOC];
GPCategory *category;
if ((category = [GPCategory MR_findFirstByAttribute:@"catId" withValue:dic[@"mainAttribute"] inContext:backgroundMOC])) {
NSLog(@"Found with mainAttribute %@", dic[@"mainAttribute"]);
[deal addDealCategoryObject:category];
}
if([backgroundMOC hasChanges]) {
NSError * error;
[backgroundMOC save:&error];
[self.model.context performBlockAndWait:^{
if([self.model.context hasChanges]) {
NSError * error;
[self.model.context save:&error];
}
}];
}
}
}];
You may lack saving the MOC chain. For clarity, I have replaced the keyword private
with the variable name backgroundMOC
.
On the question above, I can only assume that the line NSManagedObjectContext *private = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
is technically similar to:
- (NSManagedObjectContext *)backgroundMOC:(NSManagedObjectContext *)mainMOC
{
NSManagedObjectContext * threadManagedObjectContext = [[NSManagedObjectContext alloc]
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[threadManagedObjectContext setParentContext:mainMOC];
[threadManagedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
return threadManagedObjectContext;
}
passing self.model.context
as mainMOC, with a self.model.context
and a setMergePolicy
.
Similarly, I must assume that self.model saveWithErrorBlock
is technically identical to:
[mainMOC performBlockAndWait:^{
if([mainMOC hasChanges]) {
NSError * error;
[mainMOC save:&error];
// handle error
}
}];
If so, the same should be said of the backgroundMOC
(your private
reference):
[backgroundMOC performBlockAndWait:^{
if([backgroundMOC hasChanges]) {
NSError * error;
[backgroundMOC save:&error];
// handle error
}
}];
In other words, you want to ensure that your backgroundMOC
and mainMOC
save operation is executed from their respective threads, with performBlockAndWait
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With