Make readwrite variables from an API class which variables are readonly - objective-c

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
}

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.

Yeah because APIAxes defined the properties as readonly, your hands are tied. Generally what they'll give you is an initializer method that takes arguments that set those properties, but that doesn't appear to be the case?

Related

Simple Class Extension / Inheritance Clarification

I've been writing Objective-C for a few years now, and decided to go back and learn the very basics to help me write even better code. I'm trying to learn all about instance variables, inheritance and class extensions. I've been reading up on all three, but there is one thing that boggles my mind. I have a simple app that contains 2 classes, Person, Male (inherits from Person), and of course Main (which imports the Male class, therefore being able to access the instance variables found in both Person and Male).
The code is simple, and for the sake of space I won't post all of it. Basically Main takes these variables and plays around with them. This is the part that is boggling my mind:
#interface Person : NSObject {
float heightInMeters;
int weightInKilos;
}
#property float heightInMeters;
#property int weightInKilos;
#end
When I delete the brackets and variable declarations, leaving it like this:
#interface Person : NSObject
#property float heightInMeters;
#property int weightInKilos;
#end
The code still inherits and executes just fine.
1. What is the point of even declaring them there in the first place if we can just create two properties?
2. why create two instance variables AND properties to correspond with them?
3. I know that we can declare the variables in the .m instead to keep them private to the class and everything that subclasses it. like this:
#implementation Person {
float heightInMeters;
int weightInKilos;
}
What is the difference here? I feel like I'm missing a lot of basics. Is there a simplistic way of putting this all in perspective?
When you declare a #property, the compiler will automatically synthesize the variable prefixed with an underscore, a getter method, and a setter method.
#interface MyClass ()
#property(strong, nonatomic) NSString *myString;
#end
In this example the compiler would syhtnesize the variable as _myString, the getter as
-(NSString *)myString
and the setter as
-(void)setMyString:(NSString *)string
The keywords after "#property" (strong, nonatomic) define the property's attributes. strong, the default, implies ownership, meaning that in this case MyClass instances will essentially be responsible for the retain/release of their respective myString objects. nonatomic means the variable is not guaranteed to always be a valid value in a multithreaded environment, for example if the getter is called at the same time as the setter.
Additionally, the compiler will treat dot syntax used to retrieve/set instance variables as calls to the appropriate getter/setter methods. Therefore, given an instance of MyClass
MyClass *exampleClass = [[MyClass alloc] init];
Both of the following are equivalent statements:
NSString *string1 = example.myString; // dot syntax
NSString *string1 = [example myString]; // explicit call to the getter method
For further reading, take a look at Apple's Programming with Objective-C Guide.
As for your specific questions:
1. What is the point of even declaring them there in the first place if we can just create two properties?
It's actually not a good idea to declare variables explicitly as public variables in your MyClass.h file (or in most other cases). Instead, declaring them as properties automatically creates a private variable (and accessor methods), making adhering to OOP best practices a little easier. So there is no point in declaring
// MyClass.h
#interface MyClass : NSObject {
NSString *myString // public variables not good
}
Also because of what I stated above regarding dot syntax, if you use self.myString internally in MyClass.m or instanceOfMyClass.myString externally, the public variable myString will never even be touched because the synthesized variable is named _myString.
2. Why create two instance variables AND properties to correspond with them?
See above--you don't need two instance variables, only one.
3. I know that we can declare the variables in the .m instead to keep them private to the class and everything that subclasses it. What is the difference here? I feel like I'm missing a lot of basics. Is there a simplistic way of putting this all in perspective?
If you declare your variables privately in the #implementation part of your .m file, the compiler won't be able to help you by synthesizing the getters and setters. Even as private methods, getters and setters can help reduce complexity in your code, for example checking for the validity of variable values. (Note: you can override accessor methods.)
// MyClass.m
#interface MyClass () // private interface
#property(nonatomic, strong) NSString *myString;
#end
#implementation MyClass {
// no more need for private variables!
// compiler will synthesize NSString *_myString and accessors
}
-(void)setMyString:(NSString *)string { // overwrite setter
// no empty strings allowed in our object (for the sake of example)
NSAssert([string length] > 0, #"String must not be empty");
// assign private instance variable in setter
_myString = string;
}
#end
This way, even when you subclass MyClass, the subclass will inherit the getter and setter methods that were synthesized for us by the compiler.

private fields on Objective C

What is difference of these three cases (all of them are used like private fields):
1.
#interface APLParseOperation : NSOperation
#property (copy, readonly) NSData *earthquakeData;
#end
2.
#interface APLParseOperation () <NSXMLParserDelegate>
#property (nonatomic) APLEarthquake *currentEarthquakeObject;
#property (nonatomic) NSMutableArray *currentParseBatch;
#property (nonatomic) NSMutableString *currentParsedCharacterData;
#end
3.
#implementation APLParseOperation
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
It's a good practice or smthing else?
I'm going to go through each example you gave, and describe them. I was just having trouble with this yesterday so I feel your pain.
1.
#interface APLParseOperation : NSOperation
#property (copy, readonly) NSData *earthquakeData;
#end
By using the #property keyword, the compiler automatically synthesizes your accessor methods for you, and also a backing instance variable. However, because you are using the readonly property attribute, the compiler is only synthesizing a getter method for you.
2.
#interface APLParseOperation () <NSXMLParserDelegate>
#property (nonatomic) APLEarthquake *currentEarthquakeObject;
#property (nonatomic) NSMutableArray *currentParseBatch;
#property (nonatomic) NSMutableString *currentParsedCharacterData;
#end
This second example is very similar to the first. However, because none of them have the readonly property attribute, they will all have getters and setter methods synthesized for them, as well as the backing instance variable.
3.
#implementation APLParseOperation
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
For this last example, you are just declaring instance variables. These are also private to your implementation file, where as the other 2 examples had declarations being made in your classes interface file.
No setter or getter methods are being synthesized for you by the compiler. You are simply declaring some instance variables.
In terms of private and public, your first and second examples both provide declarations that will be visible to other classes, as long as they import the current class's header file. The first example however, only provides a way to "get" the property and read it, there is no setter method because you used the readonly property attribute. With the second example, outside classes will be able to access your getter and setter methods for your property, so they can read and write.
For the third example, these are just instance variables and they are private to your class's implementation file. Basically, no outside classes will even know that they exist.
This is not private. It is still readable by outside classes, though it can't be written.
Private properties. It can be useful if you want to write custom getters and setters. If you are not using ARC, it can be helpful for memory management.
Private members. This is my favorite. It's easy to read and easy to write.
defines a public property visible to all users of the APLParseOperation class.
defines properties through an extension, making them available only to the implementation methods.
defines instance variables which are implicitly private.
Number 1 is used when you want to make your properties public. Numbers 2 and 3 are for private properties and instance variables. You can also declare instance variables in class extensions, like this:
#interface APLParseOperation () <NSXMLParserDelegate>
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
#end
There is not much difference between that and the number 3. It is a good idea to pick one style, and stick to it in all your code.
Case 1. is not private. It's a public read-only property: Reading is public, writing is only possible only in the private scope via the underlying ivar (thanks for pointing it out #mah).
Case 2. (if in a .m file) is extending the class by adding 3 private properties and making the protocol conformance private too.
Case 3. is declaring 4 private instance variables that can be used in all the implementation scope.
Objective-C best practice for private properties is case 2., as case 1. is not private at all, just read-only, and case 3. uses instance variables (aka ivar) which is less conventional than properties. More on that here: Reason to use ivars vs properties in objective c
Hope this helps,

Is using a property protecting the setter and the getter?

If im declaring a class with property for example:
#property float radius, diameter;
So any object that will be created in this class or inherits from it, will have its own instance of radius and diameter right?
And this is also mean that they have their own setter and getter too right?
What i'm trying to fully understand is how do I deal with variable access in 2 ways:
1.When I want to make sure the user is not messing with the original value.
2.When I want to limit the users for instance variables he can get access and ones that he can not.
tnx
As to the first part, yes, any subclass will inherit it's superclasses properties and methods as long as they are public. Just remember to synthesise them to get the getter and setter.
So, if you want to have a public property that can't be modified:
// This returns a copy - whatever the receiver does with it doesn't affect the original
#property (nonatomic, copy) BOOL someVariable;
// This declares the property as only having a getter - no setter
#property (nonatomic, readonly) NSArray *someArray;
Any properties declared in your header file are considered public, unless otherwise specified. If you want to have private properties, ivars or methods, declare them in your implementation file in the class continuation category:
// In your .m *above* the #implementation MyClass
#interface MyClass()
#property (nonatomic, strong) NSArray *myPrivateModel;
#end
Stamford do a great lecture series on iTunesU which I'd really recommend for learning objectiveC
Hope that helps

How to do pointer work with accessor methods in Objective-C

Basic problem statement:
I have a very good reason for doing some pointer fanciness in an app where I need to pass a decimal by reference.
So I have a class which stores many a decimal, so let's say is has a property as such:
#property (nonatomic) double myDecimalValue;
I want to pass it by reference to some other class.
[someOtherObject sendMyDecimalByReference:&myDecimalValue];
But, a problem emerges! The way that actually has to be written (because it's a property) is
[someOtherObject sendMyDecimalByReference:&decimalOrigin.myDecimalValue];
This fails to compile in objective-c
I get around it by writing the following
- (double *) myDecimalValueRef;
[someOtherObject sendMyDecimalByReference:[decimalOrigin myDecimalValue]];
Except I have dozens of these decimals and I don't want to write that stupid wrapper function for every value.
Is there a shorthand way to do this in Objective-C using just the Getter functions?
Let's just assume I have a great reason for not using NSNumber.
Thanks!
Can you use and access an instance variable directly instead of a property? Then it would work the same way as a C struct member...
#interface SomeClass : NSObject
{
#public
double myDecimalValue;
}
// Keep the getter or not, assuming you synthesize it in a way that uses the
// myDecimalValue ivar
#property (nonatomic) double myDecimalValue;
#end
Then you could access it this way:
[someOtherObject sendMyDecimalByReference:&decimalOrigin->myDecimalValue];
Of course, the robustness is limited, someOtherObject has to remain a valid object when you actually dereference the value, and if you have subclasses/superclasses, you will have to take this design into account...
While far from ideal, you could make the ivars public. I hate even saying that, but it is a possible solution.
Another option is to create a pair of properties for each decimal. Create regular property and also a reference property:
#interface Foo : NSObject
double _myDecimal;
#property (nonatomic, assign) double myDecimal;
#property (nonatomic, assign) double *myDecimalRef;
#end
#implementation Foo
#synthesize myDecimal = _myDecimal;
- (double *)myDecimalRef {
return &_myDecimal;
}
- (void)setMyDecimalRef(double *)val {
_myDecimal = *val;
}
#end
Now you can things like:
[someOtherObject sendMyDecimalByReference:decimalOrigin.myDecimalRef];
Or something like this:
*decimalOrigin.myDecimalRef = 3.14;
Have you looked at the NSValue class? It allows you to pass pointers around as objects.
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSValue_Class/Reference/Reference.html

Questions about Class Extensions and inheritance in objective-c

I do not have anything in particular to achieve, but rather I am trying to learn more about class extension.
This is the explanation of class extension directly from apple Categories and extensions:
#interface MyClass : NSObject
#property (retain, readonly) float value;
#end
// Private extension, typically hidden in the main implementation file.
#interface MyClass ()
#property (retain, readwrite) float value;
#end
it does make perfect sense to me, however, supposing I have a MyClass2 extending MyClass:
#interface MyClass2 : MyClass
#property (retain, readwrite) float value;
#end
so I have few questions, which I could easily answer if class extensions weren't involved:
at runtime, when in MyClass I am doing an assignment self.value=2 or just calling float x=self.value , which setter and getter #property are called ? MyClass or MyClass2 ?
shouldn't the compiler at least issue a warning about a readonly property being redefined ?
I know #property are backed by an ivar, so how many ivar are there in the end ? Related to this, calling the same self.value from MyClass2 point of view which ivar would set ?
First off, the properties should be 'assign' not 'retain' since they are scalar types.
Changing the writability in class extensions or subclasses are common patterns to implement publicly read-only but privately writable properties and mutable subclasses of immutable classes, respectively. The Apple Objective-C Programming Guide has a good discussion.
To answer your first question, only methods declared in MyClass, or any of its super-classes, are visible from within MyClass. Your private class extension declares the setter in scope to the implementation, so that will get called. The readwrite declaration in the interface for MyClass2 merely brings the setter in to the public scope. The implementation is still in MyClass.
The answer to your second question is no, a warning is not issued. Changing writability from read-only to read-write is valid.
Finally, there is only one ivar. Accessing it from MyClass2 affects the same ivar visible in MyClass.
You can't retain a float. Let's write (readonly) instead.
MyClass doesn't know anything about MyClass2, which seems to be a subclass of MyClass. When you write self.value = 2, it will be transformed into [self setValue:2] and the code will start at MyClass and look for a setValue method. This will have been created, because you defined value as a property. The setter method will look like
-(void) setValue:(int newValue) {
_value = newValue; // _value is the actual storage for the property value
}
and the variable _value will be the one allocated in the instance of the object MyClass that you are executing.
In fact there is just one iVar. If, In MyClass2, you write
self.value = 3;
super.value = 4;
float myFloat = self.value;
myFloat ends up equal to 4.
Presumably the compiler doesn't complain about redefining the property in MyClass because it's quite a reasonable thing to do. That way, other classes cannot write to value, but within MyClass, you can write self.value = 2; and it will work.
I did believe there were two iVars, but I was wrong. Sorry for confusing anyone. Thanks to Martin R and BradS for educating me.