简体   繁体   中英

Objective-C/Cocoa: How to set value for a readonly property?

I found that some objects are defined so that a readonly property is set by an external object, somehow. For example, in:

// skview is an instance of SKView
// skscene is an instance of SKScene
[skview presentScene:skscene]

skscene's 'view' property, which is readonly, is set to skview.

How is this possible if property skview.view is readonly? How can this behaviour be implemented in custom objects?

Thanks!

If you declare a property in you .h file and set it as readonly , you can redeclare it in the .m file (in the continuation category) as readwrite , so you can directly edit the value.

But that's just the clean way of doing things. You can also use KVC to be a bit more back-door about it and just call setValue:forKey: which bypasses any of the nice stuff you might have done to specify what you want to be public.

Check this for a description of what KVC will do to fulfil your request.

Then, if you get really desperate, you can use the Obj-C runtime to get direct access to the underlying instance variables.

The key to understanding this is to recognise the fundamental distinction between "interface" and "implementation".

The @interface defines the PUBLICLY VISIBLE face that your particular object wants to present. To the outside world, it can declare that "this value is read-only, you may not change it".

Internally, however, the implementation is free to make it read-write, to directly access the backing store that the interface is exposing, or to implement the read-only property as a computation, something that does not represent a simple variable.

For example, imagine a property called 'firstSubview' - this readonly property would be implemented by retrieving the list of all subviews, then returning the first in the array (or nil if there were none). Making this property writeable would make little sense.

Remember, an @implementation can redefine properties to be readwrite, can create its own private properties (and backing variables), etc.

Think of the contents of the .h file as primarily being for everyone EXCEPT the actual implementing .m

If you would like external projects to set this property, then you need to declare a setter. So for instance you'd have in your .h file:

@property (readonly) NSString *mySpecialString;

-(void)setMySpecialString:(NSString*)string;

Then you need to write the implementation in your .m file and you can put whatever other operations you wanted to happen at the time of assignment in there as well. However, in this case there is no point in making this property readonly, as you can both read and write it.

One way to use readonly properties is to make them readable to external classes, then to modify the corresponding ivars in the .m file, so that they are written to privately.

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