Подтвердить что ты не робот

Подкласс класса с синтезированным свойством 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.

Что мне не хватает?

4b9b3361

Ответ 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 как есть.