スーパークラスではMyClass
:
@interface MyClass : NSObject
@property (nonatomic, strong, readonly) NSString *pString;
@end
@implementation MyClass
@synthesize pString = _pString;
@end
サブクラス内MySubclass
@interface MySubclass : MyClass
@end
@implementation MySubclass
- (id)init {
if (self = [super init]) {
_pString = @"Some string";
}
return self;
}
問題は、コンパイラが_pString
はMySubclass
のメンバーですが、MyClass
で問題なくアクセスできます。
何が足りないのですか?
_pString
によって生成されるインスタンス変数@synthesize
は、private to MyClass
です。 MySubclass
がアクセスできるようにするには、protectedにする必要があります。
次のように、MyClass
の_pString
セクションに@protected
のivar宣言を追加します。
@interface MyClass : NSObject {
@protected
NSString *_pString;
}
@property (nonatomic, strong, readonly) NSString *pString;
@end
ここで、通常どおりアクセサーを合成すると、変数がサブクラスにアクセスできるようになります。
私はこの問題に精通しています。 .mクラスで変数を合成します。これは、_pString変数がインターフェイスではなく実装の一部として作成されるため、ヘッダーと一緒にインポートされないためです。解決策は、ヘッダーインターフェイスで_pStringを宣言し、それをとにかく合成することです(プライベート変数を作成する代わりに、既存の変数を使用します)。
@interface MyClass : NSObject
{
NSString *_pString; //Don't worry, it will not be public
}
@property (nonatomic, strong, readonly) NSString *pString;
@end
与えられた答えは完全にうまく機能します。これは別の答えであり、明らかにApple もう少し好きです 。
クラスの プライベート拡張子 、MyClass+Protected.h
ファイルを定義できます。これは、MyClass.m
およびMySubclass.m
に含める必要があります。
次に、この新しいファイルで、プロパティをreadwrite
として再定義します。
@interface MyClass ()
@property (strong, readwrite) NSString * pString;
@end
この代替手段では、ivar self.pString
ではなくアクセサー_pString
を使用できます。
注:pString
の定義をMyClass.h
にそのまま保持する必要があります。