Objective c 从@encoded类型字符串解码类
Objective-C的Objective c 从@encoded类型字符串解码类,objective-c,objective-c-runtime,Objective C,Objective C Runtime,Objective-C的@encode生成表示任何类型的C字符串,包括原语和类,如下所示: NSLog(@"%s", @encode(int)); // i NSLog(@"%s", @encode(float)); // f NSLog(@"%s", @encode(CGRect)); // {CGRect={CGPoint=ff}{CGSize=ff}} NSLog(@"%s", @encode(NSString)); // {NSString=#} NSLog(
@encode
生成表示任何类型的C字符串,包括原语和类,如下所示:
NSLog(@"%s", @encode(int)); // i
NSLog(@"%s", @encode(float)); // f
NSLog(@"%s", @encode(CGRect)); // {CGRect={CGPoint=ff}{CGSize=ff}}
NSLog(@"%s", @encode(NSString)); // {NSString=#}
NSLog(@"%s", @encode(UIView)); // {UIView=#@@@@fi@@I{?=b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b6b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b3b1b1b1b2b2b1}}
因此,我可以使用@encode(ClassName)
对类(包含类名的类)进行有意义的编码,但它的格式也与泛型结构的编码相同(如上面的示例所示)
现在,我的问题是,给定任何(当然是有效的)类型编码,是否有可能找出编码是否属于Objective-C类,如果是,是否有可能得到与该编码对应的类
对象
当然,我可能只是尝试从类型编码中解析类名,然后使用NSClassFromString
从中获取类,但这听起来不是正确的方法,也不是特别高效的方法。这真的是实现这一点的最佳方法吗?不幸的是,我认为没有办法确保您使用的是使用编码的类
dasblinkenlight在评论中有一个好主意,尽管他不支持其他实例变量。类的完整格式是{CLASSNAME=#IVARS}
。然而,正如我将在下面解释的那样,这也可能捕获其他结构
类被这样编码的原因是它们被@encode
像结构一样对待。{
表示结构的开头,后跟结构的名称和等号,然后是内容,最后是}
。所有类在等号后都有#
的原因是类结构中的第一个元素是class
类型,这就是这种类型的编码方式。这意味着任何以类开始的结构都将匹配此格式。如果列出了任何实例变量,它们将在#
之后进行编码。例如,下面是使用您发布的编码重建UIView的过程
Structure Encoding
struct UIView { {UIView=
Class class1; #
id id1, id2, id3, id4; @@@@ Object pointers always encode as id.
float float1; f
int int1; i
id id5, id6; @@
unsigned int uint1; I
struct /*anonymous*/ { {?=
unsigned bitfield1 : 1; b1 The type of bitfield is not encoded.
unsigned bitfield2 : 1; b1 I just chose unsigned.
...
unsigned bitfield15 : 1; b1
unsigned bitfield16 : 6; b6
unsigned bitfield17 : 1; b1
...
unsigned bitfield58 : 1; b1
unsigned bitfield59 : 3; b3
unsigned bitfield60 : 1; b1
unsigned bitfield61 : 1; b1
unsigned bitfield62 : 1; b1
unsigned bitfield63 : 2; b2
unsigned bitfield64 : 2; b2
unsigned bitfield65 : 1; b1
}; }
} }
(使用/usr/include/objc/runtime.h中的\u C.*
常量解码)
如果将此结构放入代码中(填写..
s),则@encode(UIView)
和@encode(struct UIView)
都将给出相同的结果。有趣的是,从技术上讲,以类开始结构将使其成为有效的类类型,并且您可以成功地将消息发送到指向类的指针。但是,请注意,只有在类接口中定义的实例变量才会放在编码中,因为其他变量的位置是在运行时确定的,因此不建议利用它来创建您自己的对象。没有内置的方法来做到这一点,但是有几个人看到了解析@encode
输出的逆向工程的潜力。我不拥有这个项目,但nygard's可能会为您提供一切您需要的东西,使@encode
字符串变得有意义。我想知道,除了诊断宏之外,动态确定文字类型名是否是类可能是有用的。我想我还不完全理解这个问题,但是根据@encode
用#
标记类,检查字符串是否以{
开头并以=#}
结尾,抓取中间的内容并传递给NSClassFromString
?@dasblinkenlight不是那么简单,因为有些类有不止一个实例变量(参见更新的代码示例),但它仍然非常容易解析。我只是想看看是否有更好的方法来实现这一点,因为对我来说,通过字符串解析来获取类名听起来不太安全或正确;这是您不需要的附加信息。使用NSClassFromString
是一种常用的方法。但是,它仅在类已注册的情况下工作,即ObjC运行时知道该类。如果不是,您可以使用结构信息来构建数据布局,但当然不是方法。@H2CO3,正如我在评论中所写,“仍然很容易解析”。问题不在于解析,而在于这是否是正确的方法。好像是的。