简体   繁体   中英

Subclass of class with synthesized readonly property cannot access instance variable in Objective-C

In the superclass MyClass :

@interface MyClass : NSObject

@property (nonatomic, strong, readonly) NSString *pString;

@end

@implementation MyClass

@synthesize pString = _pString;

@end

In the subclass MySubclass

@interface MySubclass : MyClass

@end

@implementation MySubclass

- (id)init {
    if (self = [super init]) {
        _pString = @"Some string";
    }
    return self;
}

The problem is that the compiler doesn't think that _pString is a member of MySubclass , but I have no problem accessing it in MyClass .

What am I missing?

The instance variable _pString produced by @synthesize is private to MyClass . You need to make it protected in order for MySubclass to be able to access it.

Add an ivar declaration for _pString in the @protected section of MyClass , like this:

@interface MyClass : NSObject {
    @protected
    NSString *_pString;
}

@property (nonatomic, strong, readonly) NSString *pString;

@end

Now synthesize the accessors as usual, and your variable will become accessible to your subclass.

I am familiar with this problem. You synthesize the variable in your .m class, so it is not imported along with the header since the _pString variable will be created as part of the implementation, and not the interface. The solution is to declare _pString in your header interface and then synthesize it anyway (it will use the existing variable instead of creating a private one).

@interface MyClass : NSObject
{
    NSString *_pString; //Don't worry, it will not be public
}

@property (nonatomic, strong, readonly) NSString *pString;

@end

The given answer works perfectly fine. This is an alternative answer, that apparently Apple likes a bit more .

You can define a private extension of your class, a MyClass+Protected.h file, which needs to be included in MyClass.m and MySubclass.m .

Then, in this new file, you redefine the property as readwrite .

@interface MyClass ()
@property (strong, readwrite) NSString * pString;
@end

This alternative allows you to use the accessor self.pString rather than the ivar _pString .

Note: you still need to keep the definition of pString in your MyClass.h as is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM