Re: How to Validate CoreData attribute value for uniqueness
Re: How to Validate CoreData attribute value for uniqueness
- Subject: Re: How to Validate CoreData attribute value for uniqueness
- From: Motti Shneor <email@hidden>
- Date: Tue, 02 Sep 2014 13:20:48 +0300
Thanks Willeke, Jerry Krinock for your great hints and suggestions.
Indeed I use cocoa-bindings to Core-Data model in my UI, via NSTableViewsColumns bound to a NSArrayController configured to work against the "Species" entity. That is why Core-Data's inherent KVO/KVC validation seemed the perfect match --- it validates BEFORE setting new value to a model attribute. My only "surprise" was that it was validating again AFTER the values were set, just before saving the context.
After trying all sorts of solutions, I finally managed to write my KVC validation method so that it works fine both when editing and for saving the context. The ideas is to check the new value against OTHER species entities, and not against ALL species entities. The fix has to do with Willeke's suggestion to test for (species objectAtIndex:0] != self) but formulated into the fetch predicate instead of post-fetch. Also I settled for a "count" fetch that should be faster.
I attach my implementation for the benefit of other readers. Here is the validate<key>:error: validation method. (should reside in the NSManagedObject subclass) - for me it would be "PMSpecies+PMExtensions.m" category.
---------
-(BOOL)validateCatalogID:(id *)ioValue error:(NSError * __autoreleasing *)outError {
if (*ioValue == nil)
return YES; // Let CoreData validate for empty/missing values
// Prepare static request and predicate to fetch OTHER species catalogID's. We'll reuse these every time we validate the edited species catalogID.
static NSFetchRequest *otherSpeciesIDsFetchRequest = nil;
static NSPredicate *otherSpeciesCatalogIDs = nil;
if (otherSpeciesIDsFetchRequest == nil) {
otherSpeciesIDsFetchRequest = [NSFetchRequest fetchRequestWithEntityName:[[self entity] name]];
otherSpeciesCatalogIDs = [NSPredicate predicateWithFormat:@"(catalogID == $ID) AND (self != $THIS_SPECIES)"];
}
otherSpeciesIDsFetchRequest.predicate = [otherSpeciesCatalogIDs predicateWithSubstitutionVariables:@{@"ID":*ioValue, @"THIS_SPECIES":self}];
NSInteger count = [self.managedObjectContext countForFetchRequest:otherSpeciesIDsFetchRequest error:nil];
if (count > 0) {
if (outError != NULL) {
NSDictionary *userInfoDict = @{ NSLocalizedDescriptionKey : [NSString stringWithFormat:NSLocalizedString(@"The ID %@ is already used for another species. Choose a unique ID.", NULL), *ioValue] };
*outError = [[NSError alloc] initWithDomain:@"PMX Validation" code:ePMXexistingCatalogID userInfo:userInfoDict];
}
return NO;
}
return YES;
}
---------
Thanks again everyone!!!
Motti Shneor.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden