Подкласс класса с синтезированным свойством readonly не может получить доступ к переменной экземпляра в Objective-C
В суперклассе 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
.
Что мне не хватает?
Ответы
Ответ 1
Переменная экземпляра _pString
, созданная @synthesize
, является закрытой для MyClass
. Вы должны сделать его защищенным, чтобы MySubclass
мог получить к нему доступ.
Добавьте объявление ivar для _pString
в разделе @protected
MyClass
, например:
@interface MyClass : NSObject {
@protected
NSString *_pString;
}
@property (nonatomic, strong, readonly) NSString *pString;
@end
Теперь синтезируйте аксессоры как обычно, и ваша переменная станет доступной для вашего подкласса.
Ответ 2
Я знаком с этой проблемой. Вы синтезируете переменную в своем классе .m, поэтому она не импортируется вместе с заголовком, так как переменная _pString будет создана как часть реализации, а не интерфейс. Решение состоит в том, чтобы объявить _pString в вашем интерфейсе заголовка, а затем синтезировать его в любом случае (он будет использовать существующую переменную вместо создания частного).
@interface MyClass : NSObject
{
NSString *_pString; //Don't worry, it will not be public
}
@property (nonatomic, strong, readonly) NSString *pString;
@end
Ответ 3
Данный ответ работает отлично. Это альтернативный ответ, который, очевидно, Apple любит немного больше.
Вы можете определить личное расширение вашего класса, файл MyClass+Protected.h
, который необходимо включить в MyClass.m
и MySubclass.m
.
Затем в этом новом файле вы переопределяете свойство как readwrite
.
@interface MyClass ()
@property (strong, readwrite) NSString * pString;
@end
Эта альтернатива позволяет вам использовать аксессор self.pString
вместо ivar _pString
.
Примечание: вам все еще нужно сохранить определение pString
в вашем MyClass.h
как есть.