Reputation: 17323
I have a form in my app that allows users to input text and save it to CoreData
in a UIManagedDocument
.
While the app is running, I'm using an NSManagedObjectContext
as the one and only context for inserting and fetching objects from this document.
The problem I have is - before saving I check for duplicates, and if I do subsequent inserts with waiting like 10 seconds, the context
doesn't acknowledge already inserted ([matches count]
returns 0) objects, and allows for duplicates.
If on the other hand I wait for some it - the result is as expected ([matches count]
returns whatever number is true).
@implementation Student (Create)
+ (Student *)withInfo:(NSDictionary *)infoDictionary inManagedContext:(NSManagedObjectContext *)context
{
Student *student = nil;
// Check for duplicates
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"];
request.predicate = [NSPredicate predicateWithFormat:@"studentID == %@", (NSString *)infoDictionary[@"studentID"]];
[request includesPendingChanges];
NSError *error = nil;
NSArray *matches = [context executeFetchRequest:request error:&error];
if (!matches || ([matches count] > 1)) {
// handle error
NSLog(@"Error happens");
for (Student *student in matches) {
[context deleteObject:student];
NSLog(@"studentID: %@", student.studentID);
}
} else if (![matches count]) {
student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:context];
NSString *studentID = (NSString *)infoDictionary[@"studentID"];
int studentIDint = [studentID intValue];
NSLog(@"studentID: %d", studentIDint);
student.studentID = [NSNumber numberWithInt:studentIDint];
student.nameFirst = infoDictionary[@"nameFirst"];
student.nameLast = infoDictionary[@"nameLast"];
// Add this students portrait as a relationship
Portrait *portrait = [Portrait portraitWithAssetURL:infoDictionary[@"PortraitAssetURL"] inManagedObjectContext:context];
student.portrait = portrait;
NSError *errorSave;
[context save:&errorSave];
NSLog(@"errorSave: %@", errorSave);
NSLog(@"creating a new student, matches count: %lu", (unsigned long)[matches count]);
} else {
student = [matches lastObject];
NSLog(@"fetching old one, count: %lu", (unsigned long)[matches count]);
}
return student;
}
@end
Upvotes: 0
Views: 245
Reputation: 1315
The code should look something like this:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"EntityName"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"uniqueID == %@", newID]
[request setPredicate:predicate];
NSError *error = nil;
NSArray *matches = [context executeFetchRequest:request error:&error];
if([matches count]){
// update record
SomeEnt *ent = [matches objectAtIndex:0];
// ent set properties
}
else{
// add new record
SomeEnt *ent = [NSEntityDescription insertNewObjectForEntityForName:@"EntityName" inManagedObjectContext:context];
// ent set properties
// ...
}
NSError *error;
[context save:&error];
Upvotes: 1
Reputation: 80271
Something in your query does not make sense. You are sorting by uniqueID but only fetching one ID, so what is the sort for? Eliminate it.
Also, it does not make sense to check for uniqueID before saving. You should instead do this check before creating the new object.
This query should be very fast and not interfere with your insert at all. Consider also setting the fetchLimit
to 1, but this is not really necessary.
NSArray *results = [self.managedObjectContext
executeFetchRequest:request error:nil];
EntityName *object;
if (results.count) {
object = results.lastObject;
}
else {
object = [NSEntityDescription insertNewObject… ];
}
Upvotes: 0
Reputation: 1718
I think you should call [context save:&error]
to save your modification to the store.
Or add [request includesPendingChanges:YES]
to allow request on pending unsaved changes.
Upvotes: 0