4

これは私がよく遭遇する状況であり、定型コードが無駄であり、私だけではないと確信できるほど十分です。これは一義的ですか、より良い方法はありますか、それとも毎回行う必要がありますか?

@interface SomeUIElement : UIView
@property CGFloat insetMargin; // <-- just an example of a UI parameter
@end

@implementation SomeElement
- (void)setInsetMargin:(CGFloat)insetMargin {
    _insetMargin = insetMargin;
    [self setNeedsDisplay]; // <-- the only thing that stops it being synthesized
}
@end

これにより、追加できるゲッターを取り除くために、ゲッターがないというコンパイル警告が発生します

- (CGFloat)insetMargin {
    return _insetMargin;
}

しかし今、ivarがないと不平を言うので(定義されたゲッターとセッターは私のために作成されていないことを意味するため)、追加する必要があります

@interface SomeUIElement () {
    CGFloat _insetMargin;
}

つまり、プロパティが変更されたときに表示を強制的に更新したいだけで、かなりのオーバーヘッドが発生します。

(a) ゲッターと ivar を作成するつもりだったことを ObjC に伝える方法があるので、セッターだけを書く必要があるか、または (b) プロパティが見た目が変わる?

Apple の SDK はこれをどのように行うのですか (UILabel ソースなど、何らかの表示方法を見逃していないと思います)。

4

1 に答える 1

5

プロパティが非アトミックであると宣言されている場合、「部分合成」を取得できます。

@property (nonatomic) CGFloat insetMargin;

デフォルトは (理由は不明ですが)アトミックです。その原子性を実装するには、両方のアクセサーが同じロック メカニズムを使用する必要があります。ただし、メソッドが合成されるとき、そのメカニズムは公開されません。したがって、両方のアクセサーを実装して独自のロックを作成するか、コンパイラに両方を実行させてそのロックを使用させる必要があります。

ただし、プロパティがアトミックでない場合は、ivar、setter、または getter の 3 つの要素の任意の組み合わせを明示的に実装でき、残りはコンパイラが処理します。ivar の名前をデフォルト (現在は先頭にアンダースコアが追加されたプロパティ名) から変更する場合は、明示的な@synthesize.

于 2013-08-03T01:05:06.813 に答える