I have to expose a private property to sub-classes. Since there is no such thing as "protected properties" in objc AFAIK, I'm using the @protected directive to expose the corresponding ivar that's synthesised by the complier.
This method appears to work, however, I'm not sure if I'm affecting the synthesis of the property and ARC in some inadvisable way?
I'm using a weak property here to show how the compiler forced me to use __weak modifier with the @protected directive, i.e. it appears the complier is aware of the two declarations and the link between them.
Superclass .h file
@interface Superclass : NSObject
{
@protected
SCNScene * __weak _scnScene;
}
@end
Superclass .m file
@interface Superclass ()
@property (weak, nonatomic) SCNScene * scnScene;
@end
@implementation Superclass
........
@end
Subclass .m file
@implementation Subclass
// Can use _scnScene just fine
_scnScene = .....
@end
Yes, it'll probably work. Don't do it this way. It's very inflexible. It forces you to declare ivars in the header, it only works with ivars, and it doesn't give you any control over read/write controls (or let you create a custom getters/setters). There isn't really a good reason to use the @
access controls anymore (not since the move to non-fragile ivars, and they weren't that useful before).
A typical way to do this is with a +Protected
header with a category. For example, you'd create a header file Superclass+Protected.h
like this:
@interface Superclass (Protected)
@property (weak, nonatomic) SCNScene * scnScene;
@end
Then you import that into any implementation files that are allowed to access scnScene
. Note that you could make this readonly
if you wanted, so internally it's writable, but to protected implementations it's only readable, and to the public, it's invisible.
This is more flexible than literal "protected" because you can import this header into any other implementation where it is appropriate. So it can also be the equivalent of C++'s "friend." Obviously naming the file and providing some header comments can be helpful to let callers know if they should or shouldn't import this file.
To any complaints that this doesn't enforce access controls (not that you made any, but for anyone that does), neither does @protected
. If I call valueForKeyPath:
, I can access protected ivars, too. ObjC helps you create "no trespassing signs" so that callers know when they're in places they shouldn't be. It doesn't try to stop programs from accessing their own memory space. (This would be a futile goal; you can always read private variables and call private functions in any language that allows raw memory access; the point of access controls is to help callers write correct code, not stop them from doing anything.)