11

プロパティを宣言するとき、宣言にさまざまな属性を入れることができます。これは、コンパイラにとって特別な意味を持ちます。

@property (nonatomic, retain) NSNumber *consumption;

ここで、nonatomicおよびretainは属性です。カスタム属性を追加して、実行時にこの属性の存在を確認することはできますか?例えば:

@property (nonatomic, retain, test) NSNumber* consumption;

私は基本的に、C#/。NETで知っている属性の使用を置き換えることができる構造を使用しているので、別の提案も歓迎します。

4

3 に答える 3

4

@property()コンパイラを変更せずに属性を追加することはできません。

@property一般に、実行時に宣言の既存の属性を取得することは、完全に推奨されないことに注意してください。ランタイムは、それを介して実行できるAPIを提供しますが、汎用的な使用を目的としたものではなく、将来変更される可能性があります。

于 2012-05-17T17:36:43.647 に答える
0

プロパティ名のNSDictionaryを属性のNSArrayにいつでも追加できます。これは、objc_setAssociatedObjectsおよびobjc_getAssociatedObjectsAPIを介して元のオブジェクトに関連付けられている基本クラスまたは個別のクラスに格納できます。

これらのAPIについては、こちらをご覧ください。コンパイラを変更する必要があるため、これは正確には探しているものではありませんが、任意のオブジェクトにメタデータを追加する方法です。

于 2012-05-17T19:44:29.607 に答える
0

プロパティにカスタム属性を追加することは一般的ではありませんが、望ましいと思います。この機能は、クラスのプロパティに関するトラバーサルをカスタム化するために使用できます。SQLを処理するときにこの機能が必要でした。:、、 ...のような属性がある場合はEXCLUDE_FROM_SELECTINCLUDE_BY_INSERT非常EXCLUDE_FROM_UPDATEに便利です。

実際、@propertyディレクティブで有効にする方法があるかどうかはわかりません。ただし、同様のことができる場合があります。

objc / runtime.hを見るとclass_replaceProperty、公式のWebサイトに記載されていない関数:が見つかります。と呼ばれる同様の関数class_addPropertyが文書化されており、前の関数の引数を理解するのに役立ちます。実際、@ propertyはこの関数を使用してプロパティ設定を行っていると思います(ただし、それを証明することはできません)。

次の関数も必要になる場合があります。

void class_copyPropertyList(...);
void property_copyAttributeList(...);
void class_getProperty(...);

これらの関数を使用することで、@propertyが実際に行うことを実行できます。

前のSQLの問題に対して私がしたことは、カスタム属性を登録するための3つの関数を定義することです。

void prepareClass(...);
void registerAttributes(...);
void endRegister(...);

そして、+initializetagartクラスの関数で登録を行うことができます。

ただし、コードを使用する(単純な@interface + @property宣言と比較してください)のは、宣言から直接プロパティ設定を確認したい場合があるため、最善の解決策ではない場合があります。そして実際には__attribute__((constructor))、マクロを使用することでそれをより良くすることができます:

@interface @endを使用すると、実際にこれを実行できます。

@interface MyVO : NSObject
__attribute__((constructor))
void prepareForMyVO(){ prepareClass(MyVO);}
@property (strong) id p1;
__attribute__((constructor))
static void registerAttrForP1(){ registerAttributes("p1", EXCLUDE_FROM_SELECT);}
@property (strong) id p2;
__attribute__((constructor))
static void registerAttrForP2(){ registerAttributes("p2", INCLUDE_BY_INSERT);}
@end
__attribute__((constructor))
static void endRegisterForMyOV(){ endRegister();};

したがって、このハードコードを処理するようにマクロを定義できます。

#define $p(clazz, zuper) class : zuper \
__attribute__((constructor)) static void prepareFor ## clazz(){ prepareClass(#MyVO);}
#define $r(p, attr) p; \
__attribute__((constructor)) static void registerAttrFor ## p(){ registerAttributes(#p, attr);}
#define $e(clazz) __attribute__((constructor)) static void endRegister ## clazz(){ endRegister();};



@interface $p(MyVO, NSObject)
@property (strong) id $r(p1, EXCLUDE_FROM_SELECT);
@property (strong) id $r(p1, INCLUDE_BY_INSERT);

@end $e(MyVO)

PS:上記のコーディングは正確なコーディングではなく、単なる例です。そして、最後のマクロソリューションが機能するかどうかはわかりませんが、これが役立つことを願っています。

于 2013-01-05T14:08:20.127 に答える