Objective c 从@encoded类型字符串解码类

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(

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)
对类(包含类名的类)进行有意义的编码,但它的格式也与泛型
结构的编码相同(如上面的示例所示)

现在,我的问题是,给定任何(当然是有效的)类型编码,是否有可能找出编码是否属于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,正如我在评论中所写,“仍然很容易解析”。问题不在于解析,而在于这是否是正确的方法。好像是的。