6

我平時懶實例化他們的getter方法我@property對象是這樣的:重寫屬性干將,在Objective-C的延遲加載

@interface MyGenericClass : UIViewController 
@property(nonatomic, readonly) UIImageView *infoImageView 
// ... 

@implementation GenericClass 

- (UIImageView *)infoImageView 
{ 
    if (!_infoImageView) { 
     _infoImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"PlaceholderInfoImage"]]; 
    } 
    return _infoImageView; 
} 

但繼承的時候,我常常會想替換一些@properties的更具體的子類。所以我想改變實例化和執行類似:

@interface MySpecificSubclass : MyGenericClass 
//... 

@implementation MySpecificSubclass 

- (UIImageView *)infoImageView 
{ 
    if (!_infoImageView) { 
     _infoImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"SpecialInfoImage"]]; 
    } 
    return _infoImageView; 
} 

但是這是不可能的,因爲子類無法訪問_infoImageView伊娃。

是我試圖做壞風格? 還是有一個共同的解決方案/最佳做法呢?我看到的唯一解決方案是使公共iVar,這感覺像違反封裝原則...

這感覺就像這是一個非常基本的問題,必須有數百萬的答案已經存在,但在搜索幾個小時我都能找到的是Objective-C: Compiler error when overriding a superclass getter and trying to access ivar ,但它沒有提供任何解決方案。

回答

8

您可能希望將_infoImageView聲明爲頭文件中的受保護變量以及屬性。 另一個想法是創建一個公共的defaultImageView方法來調用懶惰的getter。 事情是這樣的:

@interface MyGenericClass : UIViewController 
@property (nonatomic, readonly) UIImageView *infoImageView 

...

@implementation GenericClass 

- (UIImageView *)infoImageView 
{ 
    if (!_infoImageView) { 
     _infoImageView = [self defaultImageView]; 
    } 
    return _infoImageView; 
} 

- (UIImageView *)defaultImageView 
{ 
    return [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"PlaceholderInfoImage"]]; 
} 

...

@interface MySpecificSubclass : MyGenericClass 

...

@implementation MySpecificSubclass 

- (UIImageView *)defaultImageView 
{ 
    return [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SpecialInfoImage"]]; 
} 
2

由於對方回答說,聲明頭中的受保護變量。新編譯器通常不需要它,但在這種情況下,它實際上有幫助!

@interface MyGenericClass : UIViewController{ 
    UIImageView *_infoImageView 
} 
@property(nonatomic, readonly) UIImageView *infoImageView