< Previous PageNext Page > Hide TOC

Model Object Validation

There are two types of validation—property-level and inter-property. You use property-level validation methods to ensure the correctness of individual values; you use inter-property validation methods to ensure the correctness of combinations of values.

Contents:

Property-Level Validation
Inter-Property Validation


Property-Level Validation

The NSKeyValueCoding protocol specifies a method—validateValue:forKey:error:—that provides general support for validation methods in a similar way to that in which valueForKey: provides support for accessor methods. You typically do not override validateValue:forKey:error:; instead you implement custom validation methods that follow the pattern validate<Key>:error:. In the method implementation, you check the proposed new value and if it does not fit your constraints you return NO. If the error parameter is not null, you also create an NSError object that describes the problem, as illustrated in the following example.

-(BOOL)validateAge:(id *)ioValue error:(NSError **)outError {
    if (*ioValue == nil) {
        // trap this in setNilValueForKey? new NSNumber with value 0?
        return YES;
    }
    if ([*ioValue floatValue] <= 0.0) {
        if (outError != NULL) {
            NSString *errorStr = NSLocalizedStringFromTable(
                @"Age must greater than zero", @"Employee",
                @"validation: zero age error");
            NSDictionary *userInfoDict = [NSDictionary dictionaryWithObject:errorStr
                forKey:NSLocalizedDescriptionKey];
            NSError *error = [[[NSError alloc] initWithDomain:EMPLOYEE_ERROR_DOMAIN
                code:PERSON_INVALID_AGE_CODE
                userInfo:userInfoDict] autorelease];
            *outError = error;
        }
        return NO;
    }
    else {
        return YES;
    }
    // . . .

It is important to note that the input value is a pointer to object reference (an id *). This means that in principle you can change the input value. Doing so is, however, strongly discouraged, as there are potentially serious issues with memory management (see Key-Value Validation in Key-Value Coding Programming Guide). You should not invoke validateValue:forKey:error: within a custom property validation method. If you do, you will create an infinite loop when validateValue:forKey:error: is invoked at runtime.

Inter-Property Validation

It is possible for the values of all the individual attributes of an object to be valid and yet for the combination of values to be invalid. Consider, for example, an application that stores information about people including their age and whether or not they have a driving license. For a Person object, 12 might be a valid value for an age attribute, and YES is a valid value for a hasDrivingLicense attribute, but (in most countries at least) this combination of values would be invalid.

The NSKeyValueCoding protocol does not define a method for inter-property validation. Core Data, however, defines validateForUpdate: which you can co-opt for classes that do not inherit from NSManagedObject. Using validateForUpdate: also makes it easier for you to migrate your classes to Core Data in the future should you wish. An example implementation is shown in Managed Object Validation in Core Data Programming Guide.



< Previous PageNext Page > Hide TOC


© 2008 Apple Inc. All Rights Reserved. (Last updated: 2008-02-08)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.