ATValidations 0.1.1

ATValidations 0.1.1

Tests测试通过的
Lang语言 Obj-CObjective C
许可证 自定义
Released最后发布版2014年12月

Kenneth Ballenegger 维护。



  • Kenneth Ballenegger

这是今天我写的最厉害的一段 Objective-C 代码 :)

这允许你以表达式方式描述对象并在它们上执行验证。这特别有助于确保 API 响应与预期格式匹配。它允许你只对格式执行一次验证,如果通过,则假定数据是有效的。

验证围绕 ATVPredicate 对象展开。一个谓词描述了一个值是否有效(通过一个验证对象的块)。

验证的最常见用例将是对 NSDictionary 进行验证,所以让我们从如何操作的一个示例开始

NSDictionary *dict;
NSError *error = nil;
if (![dict matchesMask:@{
            @"status": ATVEqual(@200),
            @"message": ATVString(),
            @"items": ATVArrayOf(ATVDictionary(@{
                @"_id": ATVString(),
                @"type": ATVInSet(@"iap", @"currency", nil),
                @"odd_number": ATVUnion(
                    ATVNumber(),
                    ATVMatchesBlock(^(NSNumber *n, NSError **e) {
                        return ATVAssert((n.intValue % 2) != 0,
                            @"must be an odd number", e);
                    }), nil)
            }, YES)),
        } allowExtraKeys:YES error:&error]) {
    NSLog(@"failure!\n%@", error);
}

这将验证 dict 与一个掩码进行对比,指定

  • dict.status 必须是 @200
  • dict.message 必须是一个字符串
  • dict.items 必须是一个字典数组,必须匹配此掩码
    • item._id 必须是一个字符串
    • item.type 必须是 iapcurrency
    • item.odd_number 必须满足这两个谓词
      • 它必须是一个数字
      • 它必须通过传递的块谓词

最后一个示例展示了构建自定义谓词的力量。你只需提供一个块,该块接受任何 id object 作为第一个参数,并返回一个 BOOL 来验证对象。

ATVAssert 是一个方便的函数,它将简单地返回其第一个(BOOL)参数,但将在布尔值为假时在传递的指针中创建一个错误,并提供错误字符串。

以下是所有谓词的完整列表

ATVPredicate *ATVArrayOf(ATVPredicate *predicate);
ATVPredicate *ATVDictionary(NSDictionary *mask, BOOL allowExtra);

ATVPredicate *ATVNumber(void);
ATVPredicate *ATVString(void);
ATVPredicate *ATVInstanceOf(Class klass);

ATVPredicate *ATVMatchesBlock(BOOL(^)(id object, NSError **error));

ATVPredicate *ATVUnion(ATVPredicate *first, ...) NS_REQUIRES_NIL_TERMINATION;
ATVPredicate *ATVOption(ATVPredicate *first, ...) NS_REQUIRES_NIL_TERMINATION;

ATVPredicate *ATVInSet(id first, ...) NS_REQUIRES_NIL_TERMINATION;

ATVPredicate *ATVEqual(id value);
ATVPredicate *ATVExists(void);
ATVPredicate *ATVNull(void);

你还可以轻松地编写自己的。例如:

ATVPredicate *CBAPIPredicateTwohundreds(void) {
    static ATVPredicate *instance = nil;
    if (!instance) {
        instance = [ATVUnion(ATVNumber(), ATVMatchesBlock(^BOOL(NSNumber *n, NSError **e) {
            return ATVAssert(n.intValue >= 200 && n.intValue < 300, @"must be a valid status code (>=200 && <300)", e);
        }), nil) retain];
    }
    return instance;
}

实现

所有谓词对象都由一个块支持,该块返回一个布尔值表示有效性,并接受一个对象作为其第一个参数,以及一个指向 NSError 的指针作为第二个参数。本身 ATVPredicate 类只是对该块的包装。

BOOL(^myPredicateBlock)(id object, NSError **error)

/review @fannan @mkinsella