从@encoded类型字符串解码类

Gre*_*reg 6 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(@"%s", @encode(UIView));    // {UIView=#@@@@fi@@I{?=b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b6b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b3b1b1b1b2b2b1}}
Run Code Online (Sandbox Code Playgroud)

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

现在,我的问题是,给定任何(当然有效)类型编码,是否可以找出编码是否是Objective-C类,如果是,那么获取Class对应于该编码的对象?

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

ugh*_*fhw 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
    };                             }
}                                 }
Run Code Online (Sandbox Code Playgroud)

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

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