【问题标题】:Objective-C class_conformsToProtocol() bug?Objective-C class_conformsToProtocol() 错误?
【发布时间】:2023-04-04 13:26:01
【问题描述】:

我在我的 iPhone Objective-C 应用程序中遇到了一些奇怪的行为。

我正在使用一些代码来测试一个对象:

if (!class_conformsToProtocol([someVar someFunctionThatReturnsAClass], @protocol(MyProtocol)))
     [NSException raise:@"Invalid Argument" format:@"The variables returned by 'someFunctionThatReturnsAClass' Must conform to the 'myProtocol' protocol in this case."];

奇怪的是,当我有一个看起来像这样的课程时:

@interface BaseClass : NSObject<MyProtocol>

...

@end

@interface SubClass : BaseClass

...

@end

当我调用这个片段时:class_conformsToProtocol([SubClass class], @protocol(MyProtocol)),它返回NO

此外,此代码失败:

class_conformsToProtocol([NSString class], @protocol(NSObject)); // also returns NO

虽然此代码返回YES

[NSString conformsToProtocol:@protocol(NSObject)];

我在文档中遗漏了什么吗? 或者这是某种错误? (我在 iOS 4.2 上,如果这很重要的话)。

【问题讨论】:

  • 哇,这有趣...
  • 不是错误。 class_conformsToProtocol() 不检查超类。这是设计使然,因为迭代超类很简单。
  • 这和isKindOfClass vs isMemberOfClass之间的区别是一样的。在这种情况下,您正在寻找 conformsToProtocol: 方法(您可以调用您获得的类)。
  • 我实际上是来这里寻找一种方法来检查子类对协议的一致性——忽略父类的一致性(反之亦然),所以感谢您提出这个问题! :)
  • @ethanB 显然我知道正确的调用方法,就像我的帖子中一样,以及其他所有答案:)

标签: iphone objective-c class protocols


【解决方案1】:

如果这里有错误,它在文档中。

根据来源,class_conformsToProtocol() 使用class_copyProtocolList(),然后根据参数测试每个生成的协议。 class_copyProtocolList() 被记录为仅返回给定类采用的协议,而不是超类采用的协议。 class_conformsToProtocol() 因此只测试给定类是否采用协议,而不是它的超类是否采用。

文档错误是class_conformsToProtocol() 没有说明这种行为。但是,文档确实声明您通常不应使用该函数,而应改用 NSObjectconformsToProtocol: 方法。

【讨论】:

  • 这很有趣,但你一针见血。一般来说,如果有一个 Objective-C 函数做同样的事情,你真的不应该使用 C 函数。 Ex objc_loadModules vs NSBundle
【解决方案2】:

使用NSObjectconformsToProtocol:方法。

这是我尝试的一个实验:

@protocol MyProtocol

- (void) doSomething;

@end

@interface MyClass : NSObject<MyProtocol>
{
}

@end

@implementation MyClass

- (void) doSomething { 
}

@end

@interface MyOtherClass : MyClass
{

}

@end

@implementation MyOtherClass

- (void) doSomething {
}

@end


int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    MyClass *obj_one = [MyClass new];
    BOOL one_conforms = [obj_one conformsToProtocol:@protocol(MyProtocol)];

    MyOtherClass *obj_two = [MyOtherClass new];
    BOOL two_conforms  = [obj_two conformsToProtocol:@protocol(MyProtocol)];
    NSLog(@"obj_one conformsToProtocol: %d", one_conforms);
    NSLog(@"obj_two conformsToProtocol: %d", two_conforms);

    [pool drain];
    return 0;
}

输出:

obj_one conformsToProtocol: 1
obj_two conformsToProtocol: 1

鉴于:

MyOtherClass *obj_two = [MyOtherClass new];
BOOL conforms_two = class_conformsToProtocol([obj_two class], @protocol(MyProtocol));
NSLog(@"obj_two conformsToProtocol: %d", conforms_two);

输出:

obj_two conformsToProtocol: 0

判决:

这是class_conformsToProtocol的一个bug,使用NSObjectconformsToProtocol:方法

class_conformsToProtocol 不同,NSObjectconformsToProtocol: 方法也会检查超类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-20
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多