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 (Cocoa-dev@lists.apple.com)

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 arch...@mail-archive.com

Reply via email to