I discovered a strange behaviour when working with a property, that was inherited as readonly and than redeclared in the inherited class as readwrite
In Ah
@interface A : NSObject
@property (nonatomic, strong, readonly) NSObject * someProperty;
@end
In Bh
@interface B : A
// no matter if here
// @property (nonatomic, strong, readwrite) NSObject * someProperty;
- (void)foo;
@end
In Bm
@interface B()
// no matter if here
@property (nonatomic, strong, readwrite) NSObject * someProperty;
@end
@implementation B
- (void)foo {
NSLog(@"%@", self.someProperty);
// crash here with unrecognized selector setSomeProperty:
self.someProperty = [NSObject new];
}
@end
calling
self.someProperty = [NSObject new];
causes the code to crash on unrecognized selector "setSomeProperty:"
investigation showed, that it looks like the setter did not get synthetized, even when declared as readwrite
Why is this happening? The compiler didnt indicate any warning for this to happen, nor i found anywhere this behaviour documented
Add a @synthesize
directive to the Bm file and the crash will go away:
@synthesize someProperty = _someProperty;
The problem is that since in the parent class you declared the property as readonly
there is no setter synthesized for it. And the subclasses inherit this behavior. Even if you redeclare the property to be readwrite
in the subclass. The @synthesize
command will instruct the compiler to generate the accessor methods for class B again.
Hope this helps!
I cannot give you an official reference, but this is what I experienced: For a property inherited from a superclass , the compiler does not generate any accessor methods.
In your case, the property is declared as readonly
in class A, so that the compiler creates only a getter method. The re-declaration in class B does not create any additional accessor methods. The reason might be that class B does not know "how" the property is realised in class A (it need not be an instance variable).
So the property declaration in the subclass is only a "promise" to the compiler that getter and setter functions will be available at runtime (similar to a @dynamic declaration). If there is no setter then you will get a runtime exception.
So a use case of re-declaring the property in the subclass would be if the superclass declares the property as read-only in the public interface, but as read-write in the ( private ) class extension:
// A.h
@interface A : NSObject
@property (nonatomic, strong, readonly) NSObject * someProperty;
@end
// A.m
@interface A()
@property (nonatomic, strong, readwrite) NSObject * someProperty;
@end
@implementation A
@end
In this case, both setter and getter are created in the class A, and class B can re-declare the property as read-write in its implementation.
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.