Have you thought about a different approach?

Since most of the digits have interpreted meanings, how about offering an 
alternative way to specifying the catalogID — namely by a dialog which lets the 
user specify each of the attributes which make up the catalogID (by using some 
sort of list selection technique; popup menu, radio button group, list, etc). 
Then, everything except for the “free” digits will be COMPUTABLE. You can then 
implement whatever strategy you want for calculating the “free” digits (such as 
a checksum, an index value, etc).

The result is that the user will NOT enter the catalogID, but will instead 
enter the unique information from which the catalogID is calculated. This 
should eliminate most errors (except, of course, for the user mis-entering the 
attribute information). 

The final check would be to do a simple fetch on the existing database using 
the newly-constructed catalogID. If the newly-constructed catalogID is 
(correctly) unique, the fetch will return nil. A non-nil result means that 
there is a duplicate.

Does this sound useful in your environment??

Cheers,

Rick Aurbach
Aurbach & Associates, Inc.

On Aug 30, 2014, at 2:00 PM, cocoa-dev-requ...@lists.apple.com wrote:

> Date: Sat, 30 Aug 2014 13:58:34 +0300
> From: Motti Shneor <su...@bezeqint.net>
> To: cocoa-dev@lists.apple.com
> Subject: How to Validate CoreData attribute value for uniqueness
> Message-ID: <270bab85-1588-4d1e-bf18-35aab9556...@bezeqint.net>
> Content-Type: text/plain;     charset=us-ascii
> 
> Hello everyone. Many discussions address this in many development forums. I 
> read them all, and was frustrated NOTHING of the suggested solutions actually 
> worked. Apple's documentation adds insult to injury, completely ignoring such 
> a common need for any real-world  Core-Data modeled application.
> 
> I have an entity "Species" with a numerical attribute "catalogID" which has 
> "human" meaning (every digit will tell something about the species, plus some 
> free digits). Different species entities must have unique catalog IDs much 
> like social security number for people, or ISBN for books. I have no more 
> than few hundred "Species" entities, and they have many attributes and 
> relations.
> 
> My wish is simple. To emit an error dialog when a user tries to use an 
> existing ID when creating a new species in the UI (source/detail window), or 
> when trying to edit the ID of an existing species, changing it to a value 
> taken for another species.
> 
> After much reading, I implemented KVC validation (validate<key>:error:) in my 
> NSManagedObject subclass "PMSpecies" like thus:
> 
> -(BOOL)validateCatalogID:(id *)ioValue error:(NSError * __autoreleasing 
> *)outError {
>    // Prepare optimized static request to only fetch all species catalogID's 
> for reuse every time we validate the edited species catalogID.
>    static NSFetchRequest *allSpeciesIDsFetchRequest = nil;
>    if (allSpeciesIDsFetchRequest == nil) {
>        allSpeciesIDsFetchRequest = [NSFetchRequest 
> fetchRequestWithEntityName:[[self entity] name]];
>        [allSpeciesIDsFetchRequest setPropertiesToFetch:@[ @"catalogID" ]];
>        [allSpeciesIDsFetchRequest setResultType: NSDictionaryResultType];
>    }
>    NSArray *allSpecies = [self.managedObjectContext 
> executeFetchRequest:allSpeciesIDsFetchRequest error:nil];
>    NSArray *allCatalogIDs = [allSpecies valueForKeyPath:@"catalogID"];
>    if ([allCatalogIDs containsObject:*ioValue]) {
>        if (outError != NULL) {
>            NSDictionary *userInfoDict = @{ NSLocalizedDescriptionKey : 
> [NSString stringWithFormat:NSLocalizedString(@"The ID %@ is already taken by 
> another species. Please use a unique ID.", NULL), *ioValue] };
>            *outError = [[NSError alloc] initWithDomain:@"Model Validation" 
> code:eExistingCatalogID userInfo:userInfoDict];
>        }
>        return NO;
>    }
>    return YES; // valid ID
> }
> 
> 
> I was happy enough to see that the bound NSTextField in the UI now behaved 
> correctly, and emitted error upon adding/updating a species with a non-unique 
> ID. However - the moment I try to save my context  to the persistent store, I 
> receive hundreds of "uniqueness" errors for every species. 
> 
> I saw that the above validation method was called for every species on every 
> save, and in those calls, my "fetch" indeed finds one occurrence of the  ID 
> --- the actual NSManagedObject's! which is OK.
> 
> So this kind of validation can't work because it is used in 2 different 
> situations - BEFORE the value was set to the attribute, and AFTER is was set 
> (upon saving the context). But in this method, I don't have a "context" 
> meaning, I don't know what kind of validation is this.
> 
> 
> I tried to implement instead the validateForInsert: and validateForUpate: 
> methods, but then the UI remains stupid, and only when the user actually 
> saves the document (long after closing the "Species" window) he receives 
> strange validation errors. In these implementations, I detect violations by 
> finding 2 or more of the same ID - not just one as the above.
> 
> Apple CoreData Programming Guide tells you the following:
> 
> NSManagedObject provides consistent hooks for validating property and 
> inter-property values. You typically should not override 
> validateValue:forKey:error:, instead you should implement methods of the form 
> validate<Key>:error:, as defined by the NSKeyValueCoding protocol. If you 
> want to validate inter-property values, you can override validateForUpdate: 
> and/or related validation methods. 
> 
> But there is absolutely nothing about inter-entity validation, such as value 
> uniqueness, value ordering dependency upon previous entities like serial IDs 
> or any cross-entity validation. 
> 
> Can anyone shed light on the subject? 
> 
> At my current situation, I would gladly settle on a UI-only validation 
> (meaning, something that would validate a text field upon end-edit-session, 
> but I don't know how to hook this on a bound-to-model field either. 
> 
> Please help...
> 
> Motti Shneor
> ---
> It is impossible to make anything foolproof, because fools are so ingenious.  
>       - Mark Twain
> 
> Make something fool-proof, and only fools will use it.
>         - My own addition


_______________________________________________

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