6

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(@"%s", @encode(UIView));    // {UIView=#@@@@fi@@I{?=b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b6b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b3b1b1b1b2b2b1}}

因此,我可以使用 对类(包含类名的类)进行有意义的编码@encode(ClassName),但它的格式也与泛型编码的格式相同struct(如上例所示)。

现在,我的问题是,鉴于任何(当然是有效的)类型编码,是否有可能找出编码是否属于 Objective-C 类,如果是,则获取与Class该编码对应的对象?

当然,我可能只是尝试从类型编码中解析出类名,并从中获取类 using NSClassFromString,但这听起来不像是正确的方法,或者特别是性能效率高。这真的是实现这一目标的最佳方式吗?

4

2 回答 2

6

不幸的是,我认为没有办法确保您正在使用编码处理类。

dasblinkenlight 在评论中有一个好主意,虽然他不支持其他实例变量。一个类的完整格式是{CLASSNAME=#IVARS}. 但是,这也可能会捕获其他结构,我将在下面解释。

类被这样编码的原因是它们被@encode. 表示结构的{开始,后面是结构的名称和等号,然后是内容,最后是}。所有类都#在等号之后的原因是类结构中的第一个元素是类型Class,这就是这种类型的编码方式。这意味着任何以 a 开头的结构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
    };                             }
}                                 }

_C_*(使用/usr/include/objc/runtime.h中的常量解码)

如果你将这个结构放在你的代码中(填充...s),两者@encode(UIView)都会@encode(struct UIView)给你相同的结果。有趣的是,从技术上讲,以类开头的结构将使其成为有效的类类型,并且您可以成功地将消息发送到指向类的指针。但是请注意,只有在类接口中定义的实例变量才会放在编码中,因为其他变量的位置是在运行时确定的,因此不建议利用这一点来创建自己的对象。

于 2013-08-10T16:19:00.057 回答
1

没有内置的方法可以做到这一点,但有几个人看到了解析@encode输出逆向工程的潜力。我不拥有这个项目,但 nygard 的class-dump可能会为您提供理解@encode字符串所需的一切。

于 2013-08-10T20:30:41.413 回答