4

いわゆる "Modern Objective-C" が登場する前は、カテゴリに新しいプロパティを作成するときに、setter メソッドと getter メソッドを実装する必要がありました。今、私たちはする必要はありません@synthesize; コンパイラは、メソッドとインスタンス変数を自動的に作成します。

しかし通常、インスタンス変数をカテゴリに追加することはできないため、最新の Objective-C でカテゴリに新しいプロパティを追加するとどうなるでしょうか? コンパイラは ivar を作成しますか?

4

3 に答える 3

7

カテゴリでプロパティを宣言できます。これは、ゲッター セレクターおよび (読み取り/書き込みの場合) セッター セレクターを宣言することと同じです。

コンパイラは、カテゴリの実装でゲッター メソッドとセッター メソッドを自動的に合成しません。カテゴリの実装でそれらを明示的に定義しない場合、コンパイラは警告を発行します。カテゴリの実装で使用@dynamicして、警告を抑制することができます。@synthesizeカテゴリの実装では使用できません。試してみると、コンパイラはエラーを出します。

コンパイラは、カテゴリで宣言されたプロパティのインスタンス変数を追加しません。カテゴリにインスタンス変数を明示的に追加することはできません。また、プロパティを使用してコンパイラをだましてそれを実行させることもできません。

iOS 6.0 を対象とする Xcode 4.5.1 を使用して、自分の主張をテストしました。

于 2012-10-16T18:17:25.670 に答える
1

property実際、いつカテゴリを追加できたのかわかりません。

Apple ドキュメントから:

カテゴリを使用すると、既存のクラスにメソッドを追加できます。ソースがないクラスにもメソッドを追加できます。

クラス拡張は、宣言するメソッドが対応するクラスのメインの @implementation ブロックに実装されている必要があることを除いて、無名カテゴリに似ています。Clang/LLVM 2.0 コンパイラを使用すると、クラス拡張でプロパティとインスタンス変数を宣言することもできます。

このメソッドは、クラス宣言を変更せずにオブジェクトにストレージを追加するために使用されます (変更できなかったり、クラスのソース コードにアクセスできない場合)。

連想参照は、OS X v10.6 以降で使用可能になり、既存のクラスへのオブジェクト インスタンス変数の追加をシミュレートします。連想参照を使用すると、クラス宣言を変更せずにストレージをオブジェクトに追加できます。これは、クラスのソース コードにアクセスできない場合や、バイナリ互換性のためにオブジェクトのレイアウトを変更できない場合に役立ちます。

だから私へのあなたの質問は間違っているようです。

出典: Apple Docs - The Objective-C プログラミング言語

于 2012-10-16T18:19:05.743 に答える
0

他の人が言ったように、これを行う方法は連想参照を使用することです。それらは、値/キー ペア パラダイムと同じよう CALayerに実装されます..基本的に..あらゆる「プロパティ」または「もの」と「関連付ける」ことができます…</p>

したがって、カテゴリ ヘッダーで…値を読み取るだけの場合は…

@property (読み取り専用) NSString *uniqueID;

次に、ゲッターを記述します…</p>

- (NSString*) uniqueID { return @"You're not special"; }

しかし、たとえば..ゲッター内から値を思いつくことはできません..外部セッター用のストレージが必要です...または使用するクラス独自の実装...次のようなセッターを作成する必要があります...

- (void) setUniqueID:(NSString*)uId 

公開する必要はありませんが、ここで「魔法」が起こります。

 …
[self setAssociatedValue:uId forKey:@"yourInternalStorageName"
                  policy:OBJC_ASSOCIATION_RETAIN_NONATOMIC];

これを見た後、これらの値の設定や取得などを容易にするためにいくつかの「個人用カテゴリ」を使用していることに気付きました..非常に便利なので、この要点に投稿しました.. …のような小さな宝石</p>

- (id) associatedValueForKey:(NSString*)key 
                     orSetTo:(id)anObject 
                      policy:(objc_AssociationPolicy) policy;

「理解」の秘訣は「ポリシー」の部分です。これらの値は…</p>

OBJC_ASSOCIATION_ASSIGN = 0,
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
OBJC_ASSOCIATION_RETAIN = 01401,
OBJC_ASSOCIATION_COPY = 01403

「通常の」宣言でプロパティを説明するときに表現されるのと同じ「個性」特性を捉えます。同じルールで値を「保存」する方法をコンパイラに指示する必要があります。

于 2013-04-10T18:53:55.330 に答える