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 protected])
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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]