3

NSCoder サポートをクラスに書き込んでいるときに、ちょっとした驚きに遭遇しました。rgb 構造体型の公開された「色」プロパティを含むクラス A があります。Aを拡張する別のクラスBがあります。

クラス B の encodeWithCoder メソッド内でカラー プロパティをエンコードするために、最初に次のように NSValue にラップしました。

[NSValue value:&(self.color)]

ただし、このコードを使用すると、次のコンパイル エラーが発生します。

Lvalue required as unary '&' operand.

NSValue でラップする前に self.color をメソッド スコープの値にコピーするだけで簡単に回避できますが、これがいつ発生するか、およびなぜ発生するかについてのルールを理解したいと思います。これは、そのプロパティ名の真のクラス フィールドが存在する必要がないため、任意の @synthesize プロパティで発生しますか?したがって、ポイントするオブジェクトが保証されていませんか?

4

2 に答える 2

4

関数 (またはメソッド) によって返されるもののアドレスを取得することはできません。ivarのアドレスを直接取得する必要がありますcolor(つまり&color)。ただし、あなたの場合は、あなたが提案したアプローチ ( id tempCol = self.color; [NSValue value:&tempCol];) を使用することをお勧めします。


ドット表記を使用すると、メソッドが呼び出されることに注意してください。

self.color
// is equal to
[self color]

&([self color])&実行時ではなくコンパイル時に解決されるため、これも不可能です。[self color]と(等しい)の戻り値は、self.colorコンパイル時にはまだわかりません ( を使用している場合でも@synthesize、Objective-C では実行時にメソッドの実装を変更できるためです (メソッドの入れ替えやカテゴリの使用など))。


何が何をするのか完全には理解していないようです@synthesizeので、説明します。:)

基本的に@synthesizeは、コンパイラは指定されたプロパティ名からメソッドとその実装を生成します。

たとえば、次のプロパティです。

@property(nonatomic, retain) NSColor *color;

この合成と一緒に:

@synthesize color;

このコードを に挿入します@implementation:

- (NSColor *)color {
  return color;
}

- (void)setColor:(NSColor *)newColor {
  if (color == newColor) { return; }
  NSColor *theOldColor = color;
  color = [newColor retain];
  [theOldColor release];
}

独自のセッターまたはゲッターを使用したい場合は@implementation、同じメソッド名を使用して でこれらを定義するだけです。たとえば、まだ何も設定されていない場合は、デフォルトの色を返すことができます。

- (NSColor *)color {
  if (color) { return color; }
  return [NSColor whiteColor];
}

これで、コンパイラはセッターを生成しますが、ゲッターは生成しません。指定したゲッターを使用しますが、self.color.


プロパティに関する Apple のガイドをご覧になることをお勧めします。

于 2011-08-18T18:47:55.077 に答える
3

ルールは簡単です。コンパイラはプロパティ アクセスを有効にします。

self.color

メソッド呼び出しに*

[self color]

つまり、&(self.color)に変わります&([self color])。メソッド呼び出しのアドレスを取得できないため、コンパイラは不平を言います。


*プロパティに割り当てていた場合、割り当てはセッターへの呼び出しに変換されます: self.color = aColor;-> [self setColor:aColor];.

于 2011-08-18T18:49:34.087 に答える