2012-05-17 4 views
11

は、私は、コンパイラのために特別な意味を持つことになりますされ、宣言の中でさまざまな属性を置くことができます。Objective-Cのメンバーにカスタム属性を指定できますか?私はプロパティを宣言すると

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

nonatomicretainは属性です。カスタム属性を追加して実行時にこの属性の存在を確認できるかどうか。例えば: - その代替の提案も歓迎している

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

私は基本的に、私はC#/。NETからそれらを知っているように属性の使用を置き換えることができ構築物について使用しています。

+1

http://stackoverflow.com/questions/4919021/custom-property-attributes-in-objective-c – rishi

+0

@rishi、ありがとうございます。私の具体的な状況は、この質問に対する答えには本当に満足していません。他の戻り値の型を作成することはできません。私はそれが可能かどうかの答えを探しています - もしそうなら、どうしたらいいですか。 – driis

+0

残念ながら、コンパイラを変更することはありません。 –

答えて

4

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

一般に、実行時に既存の属性である@propertyの宣言を掘り下げることは、かなり徹底的にお勧めできません。ランタイムにはAPIを提供していますが、一般的な目的で使用することは意図されておらず、今後変更される可能性があります。

+0

私はクラスのすべてのプロパティを繰り返し処理し、自動的にRestKitマッピングを作成するメソッドを実装しました。なぜ不動産を荒廃させるのが落ちるのですか? – Nick

+0

@ニックそれは壊れやすいです。誰かが任意にカテゴリまたはスーパークラスでプロパティを追加できます。あるいは、誰かがプロパティ宣言なしでsetter/getterメソッドのペアを作成するかもしれません。あるいは、RestKitマッピングに参加する予定のないプロパティを宣言するかもしれません。エンド・アプリケーションよりもフレームワーク・インプリメンターの問題が多いですが、明示的な「+(NSArray *)attributesParticipatingInRestMapping」タイプの問合せメソッドを使用すると、時間の経過とともにメンテナンスの頭痛が軽減される可能性があります。デベロッパーが手動でそのセットに追加することを要求することは、大変面倒ではなく、自己文書化です。 – bbum

0

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

これらのAPIの詳細については、hereを参照してください。コンパイラを変更する必要があるので、あなたが探しているものではありませんが、どのオブジェクトにもメタデータを追加する方法です。

0

プロパティにカスタム属性を追加するのは一般的ではありませんが望ましいと思います。この機能は、クラスのプロパティに関するカスタムトラバーサルに使用できます。私はSQLを扱うときにこの機能が必要でした。例えば、EXCLUDE_FROM_SELECTINCLUDE_BY_INSERTEXCLUDE_FROM_UPDATEのような属性を持っていれば、それは非常に良いでしょう。

実際、@propertyディレクティブで有効にする方法があるかどうかはわかりません。しかし、私たちは同様のことをする可能性があります:

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

あなたはまた、次のような機能が必要になる場合があります

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

、これらの機能を使用することによって、あなたが実際に何をするか@property何かを行うことができます。

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

をそして、我々はあなたのtagartクラスの+initialize機能のレジスタ操作を行うことができます:私は、以前のSQLの問題のためにした何

は、カスタム属性を登録するには3つの機能を定義することです。

しかし、宣言から直接プロパティ設定を見たい場合があるので、コード(単純な@interface + @property宣言と比較して)を使用することは最良の解決策ではないかもしれません。

:あなたはこの打ちを処理するために、あなたのマクロを定義することができ、したがって、

@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();}; 

:あなたはこれをやって

は@interfaceの@endが実際に許可する:そして、実際に我々は__attribute__((constructor))とマクロを使用することによって、より良い、それを行うことができます

#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:上記のコーディングは正確なコーディングではなく、単なる例です。最後のマクロソリューションが動作するかどうかはわかりません。 これが役立つことを願っています。

関連する問題