【问题标题】:Determine whether argument is a class or a protocol确定参数是类还是协议
【发布时间】:2014-03-07 04:39:39
【问题描述】:

我有以下方法。我目前使用 try/catch 块来确定参数是类还是协议,似乎它导致了内存泄漏。判断x是类还是协议的正确方法是什么?

[self _injectMacro:[MyClass class]];
[self _injectMacro:@protocol(MyProtocol)];

+ (id)_injectMacro:(id)x
{
    @try {
        return NSStringFromProtocol(x);
    }
    @catch (NSException *exception) {

    }

    @try {
        return NSStringFromClass(x);
    }
    @catch (NSException *exception) {

    }

    return nil;
}

【问题讨论】:

  • 这两种方法都没有记录如果类/协议不存在会发生什么。即使您的代码今天可以工作,但明天可能就不行了。
  • Cocoa 通常不是异常安全的。捕获后继续可能会导致问题——例如内存泄漏。另一方面,据我所知,这些函数不会引发异常。这段代码真的符合你的预期吗?
  • @JoshCaswell 谢谢。你是对的,我的代码总是通过第一次尝试,它是有效的。当我切换两个 try-and-catch 的位置时,它开始抛出 EXC_Bad_Access,所以它并没有真正捕捉到异常
  • 如果这些函数不直接调用适当的运行时函数class_getName()protocol_getName(),我会感到惊讶,这两个函数都试图取消引用它们的参数,例如@987654325 @

标签: objective-c class protocols


【解决方案1】:

您可以使用isKindOfClass 来判断id 是否是协议:

id x = [NSObject class];
id y = @protocol(NSObject); 
NSLog(@"%d", [x isKindOfClass:[Protocol class]]); // 0
NSLog(@"%d", [y isKindOfClass:[Protocol class]]); // 1

您必须导入ObjectiveC.Protocol 模块才能使用Protocol

@import ObjectiveC.Protocol;

或者如果你不使用模块,只需导入协议头:

#import <objc/Protocol.h>

要检查id 是类还是实例,请查看this answer

【讨论】:

  • 在导入时出现编译错误。程序中出现意外的“@”
  • 这是新的模块语法。试试#import &lt;objc/Protocol.h&gt;,@aryaxt。
  • @JoshCaswell 似乎不起作用,对你有用吗?
  • @JoshCaswell 谢谢,我必须在构建设置中将“启用模块”设置为“是”。这意味着任何需要使用代码的项目都必须这样做。我想知道是否还有其他方法。我现在就用它。再次感谢您的快速解答
  • @aryaxt:正如 Josh 指出的,您可以使用旧的 #import 语法。我已经更新了我的答案。
猜你喜欢
  • 2020-04-15
  • 2021-01-25
  • 2011-08-20
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
  • 1970-01-01
  • 2019-02-07
  • 2015-08-05
相关资源
最近更新 更多