Search code examples
objective-cencapsulationreadonlygetter-setterread-write

Make readwrite variables from an API class which variables are readonly


I'm trying to readwrite variables from an API class which variables are readonly

Is it possible to get their setters from those readonly variables?

Please note that I have no access to this classes since there are from a private API.

Here is one example:

Private APIAxes.h

@interface APIAxes

@property (nonatomic, readonly) double x;

@property (nonatomic, readonly) double y;

@property (nonatomic, readonly) double z; 

@end

My AxesClass.m

@property (nonatomic) APIAxes *apiA;
- (void)updateAxes
{
    APIAxes *temp = [APIAxes alloc];
    temp.x = 0.1;  //Error x variable is readonly
    temp.y = 0.2;  //Error y variable is readonly
    temp.z = 0.3;  //Error z variable is readonly

    self.apiA = temp; // This works
}

Solution

  • If there's no initializer for this APIAxes class, and no setters, then it sounds like you really shouldn't try to do this. Granted that the class appears to be a pseudo-struct, a simple data object that can be put into NS collections, but absent a guarantee that an APIAxes instance won't change once it's been handed out to you, you stand a good chance of causing mysterious library-internal problems by monkeying with the values. If the library authors had accounted for this, they would have provided setters, or at the very least a constructor.

    Now, having given the foot-shooting warning... You should be able to use Key-Value Coding to modify these values. I say "should" because, as Itai Ferber notes below, it relies on a particular naming convention, and it's possible to implement a class so that KVC won't work. But declared properties were implemented with KVC in mind, so if these are standard properties, you're all set.

    KVC can change a property value even absent a setter: it will find the ivar itself if necessary via the ObjC runtime library. The only thing to note is that since these properties are primitives, you need to box the new values into NSNumbers first.

    So [temp setValue:@(0.1) forKey:@"x"]; should do the trick.