Can someone walk me through an example of how to use key value validation in IOS? I am confused.
I am writing a Payments SDK, where people pass in credit card number, security code, etc to a Card class, and I need to validate these values. For example, make sure the credit card number is valid.
Is it possible to do automatic validation?
Also, can we call all of the validators at once?
Like if I have a Card class, can I call if([card isValid]) to call all of the validate functions at once without doing so myself? like:
Card * card = [[Card alloc] init];
card.number = @"424242...";
card.securityCode = @"455";
card.expirationMonth = @"";
card.expirationYear = @"";
if([card isValid]) {
Thanks for your help!
Here's an example of key-value validation.
According to Apple:
Key-value coding provides a consistent API for validating a property value. The validation infrastructure provides a class the opportunity to accept a value, provide an alternate value, or deny the new value for a property and give a reason for the error.
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/KeyValueCoding/Articles/Validation.html
Method Signature
-(BOOL)validateName:(id *)ioValue error:(NSError * __autoreleasing *)outError {
// Implementation specific code.
return ...;
}
Properly calling the method
Apple: You can call validation methods directly, or by invoking validateValue:forKey:error: and specifying the key.
Ours:
//Shows random use of this
-(void)myRandomMethod{
NSError *error;
BOOL validCreditCard = [self validateCreditCard:myCreditCard error:error];
}
Our test implementation of your request
//Validate credit card
-(BOOL)validateCreditCard:(id *)ioValue error:(NSError * )outError{
Card *card = (Card*)ioValue;
//Validate different parts
BOOL validNumber = [self validateCardNumber:card.number error:outError];
BOOL validExpiration = [self validateExpiration:card.expiration error:outError];
BOOL validSecurityCode = [self validateSecurityCode:card.securityCode error:outError];
//If all are valid, success
if (validNumber && validExpiration && validSecurityCode) {
return YES;
//No success
}else{
return NO;
}
}
-(BOOL)validateExpiration:(id *)ioValue error:(NSError * )outError{
BOOL isExpired = false;
//Implement expiration
return isExpired;
}
-(BOOL)validateSecurityCode:(id *)ioValue error:(NSError * )outError{
//card security code should not be nil and more than 3 characters long
if ((*ioValue == nil) || ([(NSString *)*ioValue length] < 3)) {
//Make sure error us not null
if (outError != NULL) {
//Localized string
NSString *errorString = NSLocalizedString(
@"A card's security code must be at least three digits long",
@"validation: Card, too short expiration error");
//Place into dict so we can add it to the error
NSDictionary *userInfoDict = @{ NSLocalizedDescriptionKey : errorString };
//Error
*outError = [[NSError alloc] initWithDomain:CARD_ERROR_DOMAIN
code:CARD_INVALID_SECURITY_CODE
userInfo:userInfoDict];
}
return NO;
}
return YES;
}
-(BOOL)validateCardNumber:(id *)ioValue error:(NSError * )outError{
BOOL isValid = false;
//Implement card number verification
return isValid;
}
The link provided by Susan has all the detail you should need. An example implementation would be like this:
- (BOOL)validateSecurityCode:(id *)ioValue
error:(NSError * __autoreleasing *)outError
{
// The securityCode must be a numeric value exactly 3 digits long
NSString *testValue = (NSString *)*ioValue;
if (([testValue length]!=3) || ![testValue isInteger])) {
if (outError != NULL) {
NSString *errorString = NSLocalizedString(
@"A Security Code must be exactly 3 characters long.",
@"validation: Security Code, invalid value");
NSDictionary *userInfoDict = @{ NSLocalizedDescriptionKey : errorString };
*outError = [[NSError alloc] initWithDomain:SECURITYCODE_ERROR_DOMAIN
code:SECURITYCODE_INVALID_NAME_CODE
userInfo:userInfoDict];
}
return NO;
}
return YES;
}
Note: I used NSString -isInteger
from this post.
The manual says
You can call validation methods directly, or by invoking validateValue:forKey:error: and specifying the key.
The advantage of this is that your - (BOOL)isValid
method can be very simply.
- (BOOL)isValid
{
static NSArray *keys = nil;
static dispatch_once_t once;
dispatch_once(&once, ^{
keys = @[@"securityCode", @"number", @"expirationMonth", @"expirationYear"];
});
NSError *error = nil;
for (NSString *aProperty in keys) {
BOOL valid = [self validateValue:[self valueForKey:aProperty]
forKey:aProperty
error:&error];
if (!valid) {
NSLog("Validation Error: %@", error);
return NO;
}
}
return YES;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With