我有以下代码,例如:
@interface LOSHeadlineMetricsService : NSObject {
id<LOSHeadlineMetricsServiceDelegate>delegate;
}
@interface LOSHeadlineMetricsService : NSObject {
id<LOSHeadlineMetricsServiceDelegate>delegate;
}
,协议看起来像
在委托的客户端运行时,我想引发一个异常,它通过反射抛出协议“LOSHeadlineMetricsServiceDelegate”的名称。我怎样才能做到这一点?
@protocol LOSHeadlineMetricsServiceDelegate <NSObject>
- (void) serviceDidComplete;
- (void) serviceFailed;
@end
答案 0 :(得分:2)
您可以从property_getAttributes()
函数返回的属性属性中解析它。可以通过检查第一个字符(defined to be a 'T')和第一个逗号之间的文本来确定任何属性的类型。对于对象类型,此文本的格式为@“ClassName”。 id
类型属性只有@符号,没有引号,类名或协议名称。你可以在这里相当有效地使用NSScanner
,或者正则表达式,无论你喜欢什么。
示例程序及其输出:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@protocol MyProtocol <NSObject>
- (void)someMethod;
@end
@interface MyObject : NSObject
@property (strong) id<MyProtocol> implementor;
@end
@implementation MyObject
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
objc_property_t property = class_getProperty([MyObject class], "implementor");
const char *propertyAttributes = property_getAttributes(property);
NSLog(@"property attributes = %s", propertyAttributes);
}
return 0;
}
该计划的输出是
2013-03-28 16:39:17.401 PropertyReflection[56502:303] property attributes = T@"<MyProtocol>",&,V_implementor
现在,正如Kevin Ballard指出的那样,谨慎地注意到这种行为与文档相矛盾,后者指出T之后的字符串是属性类型的@encode
字符串。当我写这篇文章时,我认为是这样的。但是在检查之后,@encode(id<MyProtocol>)
的结果确实只是“@”,因此使用此风险需要您自担风险。当然,解析该字符串的任何代码都必须准备好优雅地失败,而不是依赖于任务关键型数据提取。如果希望这些信息更像是为了方便而不是为了必要,那么我认为这是适合继续前进的。
答案 1 :(得分:1)
你做不到。在编译期间抛弃obj-c对象的静态类型信息。在运行时,你所知道的是它是一个obj-c对象(在这种情况下,“it”是一个属性/ ivar)。
更新:Carl Veazey的回答表明该信息确实存在于协议中。经过测试,我看到了同样的事情。但是,这完全没有记录,我建议不要依赖它来获取实际代码。