TWTValidation 1.1

TWTValidation 1.1

测试已测试
Lang语言 Obj-CObjective C
许可证 MIT
发布最后发布2014年12月

Cocoapods AdminDuncan LewisPrachi Gauriar 维护。



  • Two Toasters

TWTValidation 是一个用于声明性验证数据的 Cocoa 框架。它提供了一种验证单一对象和集合,并通过使用逻辑运算符组合多个验证器来创建更复杂的验证的机制。

1.1 版的新功能

TWTValidation 1.1 添加了多个新验证器和更新了现有验证器以变得更加灵活。

新增内容

  • TWTValueSetValidator 验证值是否在有效值的集合中。
  • TwTPrefixStringValidator 确保字符串有给定的前缀。
  • TwTSuffixStringValidator 确保字符串有给定的后缀。
  • TWTSubstringStringValidator 验证字符串是否包含特定的子字符串。
  • TWTWildcardPatternStringValidator 验证字符串是否匹配通配符模式。通配符模式支持使用 *? 通配符字符。
  • TWTCharacterSetStringValidator 验证字符串仅包含给定字符集中的字符。

更新内容

  • TWTCollectionValidator 在尝试验证值之前检查值是否响应 -count 并遵守 NSFastEnumeration 协议。以前,如果值不符合那些标准,则会在 -validateValue:error: 中发生崩溃。
  • 同样,TWTKeyedCollectionValidator 在尝试验证值之前检查值是否响应 -count-objectForKey: 并遵守 NSFastEnumeration 协议。
  • TWTNumberValidator 现在允许使用排他性的最小和最大值,分别验证值是否严格大于最小值或严格小于最大值。
  • TWTKeyValueCodingValidator 现在在在使用 +twt_validatorsForKey 之前会尝试使用 -twt_validatorsForKey: 来获取键的验证器。这可以实现基于实例状态的动态验证器。有关更多信息,请参阅类文档。
  • 现在,所有验证错误现在都包括失败验证器在错误的 userInfo 字典中。可以使用 -[NSError twt_failingValidator] 来检索。

特点

  • 简单、文档齐全、经过良好测试的 Objective-C API
  • 灵活的系统用于验证对象,对您的模型类几乎没有假设
  • 强大的错误报告,有助于您了解哪些验证器失败了以及原因
  • 内置用于验证数字和字符串的验证器
  • 块验证器,可以轻松创建具有自定义逻辑的验证器
  • 复合验证器,可使用逻辑运算符(如 AND、OR 和 NOT)组合验证器。
  • 集合验证器,用于验证集合的计数和元素
  • 键值集合验证器用于验证键值集合的计数、键、值和特定键值对
  • 键值编码验证器用于使用对象类定义的验证器验证对象的键和值
  • 一个易于扩展的API,用于创建您自己的可重用验证器
  • 支持iOS和OS X

安装

开始使用TWTValidation的最简单方法是通过CocoaPods安装它。

pod 'TWTValidation', '~> 1.1'

您也可以构建它,并在项目中包含构建的产品。对于OS X,只需将TWTValidation.framework添加到您的项目中。对于iOS,向您的头文件搜索路径中添加TWTValidation的公共头文件,并链接libTWTValidation.a,所有这些都可以在项目的构建输出目录中找到。

使用TWTValidation

TWTValidation提供各种用例的验证器,但不会限制您如何使用它们。TWTValidation中的所有验证器都继承自TWTValidator,这是一个抽象类,它声明了验证器的核心接口-validateValue:error:。此方法验证指定的值并返回它是否通过验证。如果值未能验证,则通过错误参数间接返回描述验证失败原因的错误。

让我们依次讨论TWTValidator的主要子类的每一个。这些都仅是可能性的概述。有关更详细的信息,请查看每个类的头文件中的文档。

值验证器

值验证器继承自TWTValueValidator。本身,TWTValueValidator只能执行一些基本的验证:它可以选择确保值是特定类的一个实例,不是nullNSNull实例。

TWTValueValidator *validator = [TWTValueValidator valueValidatorWithClass:[NSNumber class]     
                                                                allowsNil:NO 
                                                               allowsNull:YES];

NSError *error = nil;
[validator validateValue:@10 error:&error];             // Returns YES
[validator validateValue:[NSNull null] error:&error];   // Returns YES
[validator validateValue:@"foo" error:&error];          // Returns NO
[validator validateValue:nil error:&error];             // Returns NO

通过TWTValueValidator的子类TWTStringValidatorTWTNumberValidator执行更有用的验证。字符串验证器可以验证值是否为字符串并且具有给定的前缀或后缀;包含给定的子字符串;匹配指定的通配符模式或正则表达式;或者具有指定范围内的长度。

NSRegularExpression *regEx = [[NSRegularExpression alloc] initWithPattern:@"^[A-Z][a-z]+$"
                                                                  options:0
                                                                    error:NULL];

NSError *error = nil;
TWTStringValidator *validator = [TWTStringValidator stringValidatorWithRegularExpression:regEx 
                                                                                 options:0];
[validator validateValue:@"Uppercase" error:&error];    // Returns YES
[validator validateValue:@"lowercase" error:&error];    // Returns NO

validator = [TWTStringValidator stringValidatorWithMinimumLength:4 maximumLength:10];
[validator validateValue:@"Foobar" error:&error];       // Returns YES
[validator validateValue:@"Foo" error:&error];          // Returns NO

validator = [TWTStringValidator stringValidatorWithPrefix:@"foob" caseSensitive:NO];
[validator validateValue:@"Foobar" error:&error];       // Returns YES
[validator validateValue:@"Foo" error:&error];          // Returns NO

validator = [TWTStringValidator stringValidatorWithSuffix:@"oo" caseSensitive:YES];
[validator validateValue:@"Foobar" error:&error];       // Returns NO
[validator validateValue:@"Foo" error:&error];          // Returns YES

validator = [TWTStringValidator stringValidatorWithSubstring:@"OBA" caseSensitive:NO];
[validator validateValue:@"Foobar" error:&error];       // Returns YES
[validator validateValue:@"Foo" error:&error];          // Returns NO

validator = [TWTStringValidator stringValidatorWithPattern:@"*b*" caseSensitive:YES];
[validator validateValue:@"Foobar" error:&error];        // Returns YES
[validator validateValue:@"Foo" error:&error];           // Returns NO

validator = [TWTStringValidator stringValidatorWithCharacterSet:[NSCharacterSet letterCharacterSet]];
[validator validateValue:@"Foobar" error:&error];       // Returns YES
[validator validateValue:@":)" error:&error];           // Returns NO

数字验证器确保一个数字在某个范围内,并可选择没有小数部分。

TWTNumberValidator *validator = [[TWTNumberValidator alloc] initWithMinimum:@10 maximum:@20];

NSError *error = nil;
[validator validateValue:@15.333 error:&error];         // Returns YES
[validator validateValue:@3 error:&error];              // Returns NO

validator.exclusiveMinimum = YES;
[validator validateValue:@10 error:&error];              // Returns NO

validator.requiresIntegralValue = YES;
[validator validateValue:@15.333 error:&error];         // Returns NO

复合验证器

TWTCompoundValidator实例或简称为复合验证器,允许您使用逻辑运算符(如AND、OR和NOT)组合验证器。

TWTNumberValidator *rangeValidator = [TWTNumberValidator numberValidatorWithMinimum:@2 maximum:@10];
TWTCompoundValidator *notValidator = [TWTCompoundValidator notValidatorWithSubvalidator:rangeValidator];

NSError *error = nil;
[notValidator validateValue:@3 error:&error];           // Returns NO
[notValidator validateValue:@0.123 error:&error];       // Returns YES
[notValidator validateValue:@"foo" error:&error];       // Returns YES, :-(

TWTNumberValidator *numberValidator = [[TWTNumberValidator alloc] init];
NSArray *subvalidators = @[ numberValidator, notValidator ];
TWTCompoundValidator *andValidator = [TWTCompoundValidator andValidatorWithSubvalidators:subvalidators];

[andValidator validateValue:@3 error:&error];           // Returns NO
[andValidator validateValue:@0.123 error:&error];       // Returns YES
[andValidator validateValue:@"foo" error:&error];       // Returns NO, :-)

TWTNumberValidator *integralValidator = [rangeValidator copy];
integralValidator.requiresIntegralValue = YES;
subvalidators = @[ andValidator, integralValidator ];
TWTCompoundValidator *orValidator = [TWTCompoundValidator orValidatorWithSubvalidators:subvalidators];

[orValidator validateValue:@3 error:&error];            // Returns YES
[orValidator validateValue:@7.33 error:&error];         // Returns NO
[orValidator validateValue:@0 error:&error];            // Returns YES
[orValidator validateValue:@"foo" error:&error];        // Returns NO

块验证器

TWTBlockValidator允许您指定一个块来执行任意的验证。

TWTBlockValidator *validator = [[TWTBlockValidator alloc] initWithBlock:^BOOL(id value, NSError **error) {
    BOOL validated = [value isKindOfClass:[NSNumber class]] && value.integerValue % 2 == 0;
    if (!validated && error) {
        *error = [NSError twt_validationErrorWithCode:5 
                                                value:value 
                                 localizedDescription:NSLocalizedString(@"Value is not in set", nil)];
    }

    return validated;
}];

NSError *error = nil;
[validator validateValue:@"value1" error:&error];       // Returns YES
[validator validateValue:@"value4" error:&error];       // Returns NO

集合验证器

您可以使用TWTCollectionValidator实例来验证集合的计数和元素。集合验证器使用快速枚举来获取集合的元素。因此,它主要用于验证数组、集合和有序集合。但是,它可以与实现NSFastEnumeration并响应-count的任何对象一起工作。

TWTNumberValidator *countValidator = [[TWTNumberValidator alloc] initWithMinimum:@1 maximum:@3];

NSRegularExpression *regEx = [[NSRegularExpression alloc] initWithPattern:@"^[A-Z][a-z]+$"
                                                                  options:0
                                                                    error:NULL];
NSArray *elementValidators = @[ [TWTStringValidator stringValidatorWithRegularExpression:regEx 
                                                                                 options:0] ];

TWTCollectionValidator *validator = 
        [[TWTCollectionValidator alloc] initWithCountValidator:countValidator
                                             elementValidators:elementValidators];

NSError *error = nil;
id collection = [NSSet setWithObjects:@"Apple", @"Pear", @"Orange", nil];
[validator validateValue:collection error:&error];      // Returns YES

collection = @[ @"Apple", @"Pear", @"orange" ];
[validator validateValue:collection error:&error];      // Returns NO

collection = [NSOrderedSet orderedSetWithObjects:@"Apple", @"Pear", @"Orange", @"Grape", nil];
[validator validateValue:collection error:&error];      // Returns NO

键值集合验证器

要验证字典和映射表,请使用TWTKeyedCollectionValidator。这些验证器可以验证键值集合的计数、键和值,以及特定的键值对。

TWTNumberValidator *countValidator = [[TWTNumberValidator alloc] initWithMinimum:@1 maximum:@3];
TWTStringValidator *keyValidator = [[TWTStringValidator alloc] init];
TWTStringValidator *valueValidator = [[TWTNumberValidator alloc] init];

TWTNumberValidator *ageValidator = [[TWTNumberValidator alloc] initWithMinimum:@0 maximum:@130];
TWTKeyValuePairValidator *agePairValidator = [[TWTKeyValuePairValidator alloc] initWithKey:@"age"
                                                                            valueValidator:ageValidator]

TWTKeyedCollectionValidator *validator = 
        [[TWTKeyedCollectionValidator alloc] initWithCountValidator:countValidator
                                                      keyValidators:@[ keyValidator ]
                                                    valueValidators:@[ valueValidator ]
                                             keyValuePairValidators:@[ agePairValidator ]];

NSError *error = nil;
id collection = @{ @"key1" : @1 };
[validator validateValue:collection error:&error];      // Returns YES

collection = @{ @"key1" : @1, @"key2" : @2, @"key3" : @3, @"key4" : @4 };
[validator validateValue:collection error:&error];      // Returns NO

collection = @{ @1 : @2 };
[validator validateValue:collection error:&error];      // Returns NO

collection = @{ @"key1" : @"value1" };
[validator validateValue:collection error:&error];      // Returns NO

collection = @{ @"key1" : @1, @"key2" : @2, @"age" : @11 };
[validator validateValue:collection error:&error];      // Returns YES

collection = @{ @"key1" : @1, @"key2" : @2, @"age" : @-3 };
[validator validateValue:collection error:&error];      // Returns NO

键值编码验证器

在TWTValidation中,最有趣和有用的验证器可能是键值编码验证器。这些对象是TWTKeyValueCodingValidator的实例,用于验证对象针对一组符合键值编码规范的关键字值的认证。它从对象的类中获取用于每个键的验证器,与键值观察以获取影响关键字键的键路径的方式几乎相同。以下是一个示例,这最好地解释了这一点。

// Header File
@interface TWTSimplePerson : NSObject

@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, copy) NSString *lastName;
@property (nonatomic, strong) NSNumber *age;

- (BOOL)isValid;

@end


// Implementation File
#import <TWTValidation/TWTValidation.h>

@interface TWTSimplePerson ()
@property (nonatomic, strong) TWTKeyValueCodingValidator *validator;
@end


@implementation TWTSimplePerson

- (instancetype)init
{
    self = [super init];
    if (self) {
        NSSet *keys = [NSSet setWithObjects:@"firstName", @"lastName", @"age", nil];
        _validator = [[TWTKeyValueCodingValidator alloc] initWithKeys:keys];
    }

    return self;
}


- (BOOL)isValid
{
    return [self.validator validateValue:self error:NULL];
}


// Key-value coding validators get the validators for their KVC keys by invoking -twt_validatorsForKey:
// and +twt_validatorsForKey: on the value’s class. The base implementations of those methods simply check
// to see if the class implements -twt_validatorsFor«Key» and +twt_validatorsFor«Key», where «Key» is the
// capitalized form of the KVC key. When you have multiple keys that use the same validators, you can override
// this implementation. Here, we return the same validators for firstName and lastName, but rely on the 
// superclass implementation to invoke -twt_validatorsForAge to get the validators for the age key.

+ (NSSet *)twt_validatorsForKey:(NSString *)key
{
    if ([key isEqualToString:@"firstName"] || [key isEqualToString:@"lastName"]) {
        return [NSSet setWithObject:[TWTStringValidator stringValidatorWithMinimumLength:1 maximumLength:20]];        
    } 

    return [super twt_validatorsForKey:key];
}


- (NSSet *)twt_validatorsForAge
{
    return [NSSet setWithObject:[[TWTNumberValidator alloc] initWithMinimum:@0 maximum:@130]];
}

@end

要详细了解如何使用键值编码验证器,请参阅我们的示例项目。

创建自定义验证器

如果TWTValidation中的验证器不能满足您的需求,添加新验证器或扩展现有验证器都非常简单。只需继承TWTValidator或其子类之一,并重写‑validateValue:error:方法。查看任何一个TWTValidator子类可以获得更多指导。我们还在TWTValidationErrors.h中提供了一些构建错误对象的方法,以便参考。

贡献、错误报告和要求增强功能

如果您希望帮助修复错误或向TWTValidation添加功能,请向我们发送拉取请求!

我们使用GitHub问题跟踪错误、增强功能请求和支持,因此为上述任一项打开问题。

许可证

所有代码均受MIT许可证许可。您可以自由使用。