在Objective C中断言对象类

时间:2011-11-22 13:13:25

标签: objective-c class macros nsassert

我经常发现自己断言Objective-C中某个类的对象“isKindOfClass”。我是这样做的:

NSAssert([obj isKindOfClass:[AClass class]], @"%@ should be kind of class %@", obj, [[AClass class] description]);

我想知道为此做出捷径的最好方法。我正在考虑定义一个宏,例如:

#define NSClassAssert(obj, class)  NSAssert([obj isKindOfClass:class], @"%@ should be of class %@", obj, [class description])

我担心这可能会导致一些令人讨厌的难以处理的编译错误或运行时问题,这样做是否存在根本性的错误,是否有更好的方法可以做到这一点?

3 个答案:

答案 0 :(得分:3)

首先要确切地问你为什么要这样做。你说:

  

考虑到目标c的宽容和动态,我喜欢将代码设为“滥用证据”。我没有一个无法识别的选择器消息,而是告诉我该对象应该是哪个类。

如果将对象传递给与签名中声明的类型不匹配的方法,即,您执行以下操作:

- (void)doSomething:(NSArray *)array { /* Do something * }

- (void)doSomethingElse
{
    NSString *string = @"my string";
    [self doSomething:string];
}

你会收到警告,所以你应该知道编译时对象类型不匹配。

当然,当使用更通用的类型(如id)时,这不会保护您,但如果您担心无法识别的选择器,您应该检查对象是否响应该选择器而不是使用断言:

- (id)doSomething:(id)obj
{
    if ([obj respondsToSelector:@selector(calculateSomething)]) {
        return [obj calculateSomething];
    } else {
        NSLog(@"%@ does not respond to calculateSomething", obj);
    }
}

或使用协议检查方法的可用性。


然而,那说,是的,你的宏将用于你的预期目的。

答案 1 :(得分:0)

NSParameterAssert使您不必编写字符串:

NSParameterAssert([view isKindOfClass:UITableView.class]);

结果:

Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Invalid parameter not satisfying: [view isKindOfClass:UITableView.class]'

答案 2 :(得分:-1)

  

我没有收到无法识别的选择器消息,而是告诉我   我希望对象是哪一类。

测试对象是否属于特定类有助于确保使用正确类型的对象调用一段代码;例如,使用一组NSWhatEvers。 Objective-C没有开箱即用,你的代码看起来很好;我在我的代码中使用了像这样的宏

#define NSIsKindOf(obj, klass)  NSAssert([obj isKindOfClass:class], @"%@ should be of class %s but is a %@", obj, #klass, [obj class])

如果你想进入鸭子打字路线 - 即将一个选择器发送给一个来历不明的物体 - 那么respondsToSelector:,就像@mipadi指出的那样,是可行的方法。