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そのエンコーディングに対応するオブジェクトを取得することは可能ですか?

もちろん、型エンコーディングからクラス名を解析して、 を使用してクラスを取得することもできNSClassFromStringますが、それは適切な方法ではないように思えますし、特にパフォーマンス効率もよくありません。これは本当にこれを達成するための最良の方法ですか?

4

2 に答える 2

6

残念ながら、エンコーディングを使用してクラスを操作していることを確認する方法はないと思います。

dasblinkenlight はコメントで良い考えを持っていますが、彼は他のインスタンス変数をサポートしていません。クラスの完全な形式は{CLASSNAME=#IVARS}. ただし、以下で説明するように、これは潜在的に他の構造もキャッチする可能性があります。

クラスがこのようにエンコードされる理由は、クラスが によって構造体のように扱われるため@encodeです。は構造の{開始を示し、その後に構造の名前と等号、次に内容、最後に が続き}ます。すべてのクラス#の等号の後にある理由は、クラス構造の最初の要素が typeClassであり、それがこの型のエンコード方法であるためです。これが意味することは、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 のクラス ダンプは、文字列を理解するために必要なすべてのものを提供する可能性があり@encodeます。

于 2013-08-10T20:30:41.413 に答える