6

我经常发现自己断言 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])

我担心这可能会导致一些令人讨厌的难以处理的编译错误或运行时问题,这样做有什么根本上的错误吗,有没有更好的方法呢?

4

3 回答 3

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);
    }
}

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


但是,也就是说,是的,您的宏将用于您的预期目的。

于 2011-11-22T20:52:37.653 回答
0

NSParameterAssert使您免于编写字符串:

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

结果是:

Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Invalid parameter not satisfying: [view isKindOfClass:UITableView.class]'
于 2020-05-21T19:45:00.343 回答
-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指出的那样,这是要走的路。

于 2014-01-27T20:19:54.490 回答