2013-08-03 17 views
4

這是我遇到的很多情況,足以讓樣板代碼浪費並且足夠我確信我不能成爲唯一的代碼。這是單一的嗎,還有更好的方法,還是我每次都必須這樣做?客觀C習語 - 屬性,ivars和needsDisplay

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

,但現在,它抱怨我沒有伊娃(因爲一個定義getter和setter意味着一個不爲我創建的),所以我需要添加

@interface SomeUIElement() { 
    CGFloat _insetMargin; 
} 

這意味着我們正處在一個巨大的開銷只是想迫使顯示更新時,屬性更改。

是否有(a)某種方式告訴ObjC我打算爲它創建getter和ivar,所以我只需要編寫setter,或者(b)更好的方式來請求顯示更新時與視覺外觀相關的屬性發生了變化?

蘋果的SDK如何做到這一點(我假設我沒有錯過某種觀看方式,說UILabel來源)?

+0

你需要屬性是原子嗎?這就是導致合成失敗的原因,也是編譯器的抱怨。 –

+0

啊,我真的不需要原子性(或者在我很少的時候,我不介意跳箍),所以如果我在任何地方放置非原子,即使是單字數據類型,它也會爲我創建伊娃嗎?我不知道,謝謝。你應該把它放在一個答案! – Ian

+0

如果您聲明該屬性爲「@property(nonatomic,assign)CGFloat insetMargin」,那麼您不應該需要getter或ivar。 – rmaddy

回答

5

如果屬性聲明非原子你可以得到「部分合成」:

@property (nonatomic) CGFloat insetMargin; 

默認的(不明原因)是原子。爲了實現該原子性,兩個訪問器都必須使用相同的鎖定機制。儘管如此,這種機制在合成方法時並未公開。因此,您必須實現兩個訪問器並創建自己的鎖,或讓編譯器同時執行並使用其鎖。

但是,如果該屬性不是原子的,則可以顯式實現三個元素的任意組合:ivar,setter或getter,編譯器將負責處理其餘的部分。如果您想從默認值(當前是帶有下劃線的屬性名稱)更改伊娃的名稱,則還需要明確的@synthesize