New to Objective-C, and i am basically from c++ background. I am learning now objective-c and would like to get confirmation of what i understood is write or wrong?. Kindly advise.
I have the following class:
#interface Test: NSObject
{
int instance1;
}
#property int instance1;
- (void) sayHello;
#end
Class 'Test' has a instance variable instance1. If the member function ie: sayHello wants to access the variable, it has to happen through getter/setter functions. So, There are two ways to get it :
User can define.
We can get the help from the compiler?. How?.
declare the same variable as a property, and synthesize it, the the compiler
gets the code of getter/setter for us for that particular variable.
So, Untimately, getter/setter is the only way to access the variable in the method implementation, ie. both self.instance1 = 100; and instance1 = 100 need getter/setter.
Having missed both 1. and 2., there is no way to access the instance1 variable.
Also, instance1 is a pubic variable can can be accessed outside of the class with object instance.
Test *t = [[ Test alloc] init];
t.instance1 = 200;
Questions:
Is there any way to make instance1 is "private", so that I can not access the instance
variable outside the class?
Is there anything wrong in my understanding?
If the member function ie: sayHello wants to access the variable, it has to happen through getter/setter functions.
It doesn't have to. You can access ivars directly, without using accessor methods:
- (void)sayHello {
instance1 = 123;
}
You can define private ivars by declaring them in the implementation file, not the header:
#implementation Test {
int privateVar;
}
// ... additional implementation, methods etc.
#end
Note, that since Xcode 4.4 you don't have to declare your ivars anymore. You simply declare a property. The ivar and the accessor methods will be synthessized automatically.
For more details, I recommend reading my answer to this question: Declaration of variables
ion SomeDelegate.h
#interface SomeDelegate : NSWindowController {
#private
int fLanguage;
int fDBID;
bool fEndEditingIsReturn;
#public
int fIsMyLastMSG;
}
#property int language;
In SomeDelegate.mm
#implementation SomeDelegate
#synthesize language=fLanguage;
In my example you get private and public variables, private variable fLanguage has a property for synthesize accessor methods.
Related
This question already has answers here:
Error accessing generated ivars when I override setters and getters in Modern Objective-C
(3 answers)
Closed 5 years ago.
I'm learning the Swift programing language and during this I sometimes get in touch with the old Objective-C programming language and its code.
I'm an absolutely beginner and therefore I have some question for better understanding the Setter and Getter.
So, I know that I can create an instance variable through curly braces in the .h file but normally I use properties. These properties are backed by an instance variable and offer automatically a Getter and Setter Method.
Example:
Vehicle .h file:
#interface Vehicle : NSObject
#property int myProperty;
#end
Because I created this property I don't have to declare a Getter and Setter method in the vehicle.m file because they are automatically created by the compiler. So I can create a vehicle-object, set and get the value.
Example
main.m
Vehicle *myvehicle = [[vehicle alloc] init];
[myvehicle myProperty] // myvehicle.myProperty
[myvehicle setMyProperty : 10] // myvehicle.myProperty = 10;
Now I read that it is possible to override the automatically created Getter and Setter method of my created property "myProperty". When declaring my own version of the Getter and Setter I have to declare two methods in the vehicle.h and vehicle.m file. In the vehicle.m file I don't call the object by using the self keyword but by using it's automatically created instance variable (_myProperty). Is it right?
I tried it but alway get an error and I don't know why and what is the point.
Example
Vehicle .h file:
#interface Vehicle : NSObject
#property int myProperty;
-(int) myProperty; //my new Getter method
-(void) setMyProperty: (int)updatedMyProperty; //My new Setter method
#end
vehicle .m file:
#implementation Vehicle
-(int) myProperty {
if (! _myProperty) {
_myProperty = NO;
}
return _myProperty;
}
-(void) setMyProperty: (int)updatedMyProperty {
if (_myProperty == updatedMyProperty) return;
_myProperty = updatedMyProperty;
}
#end
I always get the error "Use of undeclared identifier" and I don't know why. If I understand right I don't have to declare the ivar or its name using #synthesize because the compiler automatically creates the ivar called _myProperty for me. I just have to use #synthesize when I want to change the ivar's name.
I'm not sure why I get stuck and what the point is. Could you explain it?
Thanks in advance!
If you implement all of the accessor methods, the compiler will no longer automatically synthesize the ivar for you. In this case, you have to explicitly do so yourself. E.g.
#synthesize myProperty = _myProperty;
This is only necessary when you have manually implemented all of the accessor methods. The reason is that the compiler is smart enough to know that if you're taking over the accessor methods, you may well not need the ivar, namely that you might be doing something radically different, e.g. computing values from some other property, setting/getting values from some different store, etc. You may want the compiler to synthesize the ivar (in which case you add the above #synthesize statement), but it's equally likely that you've implemented the accessor methods because no backing ivar is needed (in which case you'd omit the above #synthesize statement).
Anyway, staying with your simple example, you get something like:
#interface Vehicle : NSObject
#property (nonatomic) int myProperty; // if you don't write atomic accessor methods, you really should be explicit that this is nonatomic
// as an aside, even if you implement accessor methods, you don't have to declare them here
//
// -(int) myProperty; //my new Getter method
// -(void) setMyProperty: (int)updatedMyProperty; //My new Setter method
#end
And
#implementation Vehicle
// since you implemented all of the accessor properties, you have to manually synthesize the ivar
#synthesize myProperty = _myProperty;
- (int) myProperty {
// do whatever you want here; note, the following doesn't make sense
//
// if (! _myProperty) {
// _myProperty = NO;
// }
return _myProperty;
}
- (void)setMyProperty:(int)updatedMyProperty {
if (_myProperty == updatedMyProperty) return;
_myProperty = updatedMyProperty;
}
#end
Clearly, there's no point in writing these particular accessor methods in the above example, because you're not offering any new functionality, so you wouldn't. You'd just avail yourself of the auto-synthesized accessor methods.
But in those cases that you really need to write your own accessor methods, then you have to explicitly tell the compiler whether you need it to synthesize the ivar for you, too, or not.
Let's say I have 2 classes, A and B. A is a singleton. I declare A in B, so I can access the singletons vars in methods in B.
B then creates an instance of another class, say class C.
C Then creates an instance of another class, say class D.
What I need to do is run a method in the instance of class B, from class D, and that's what is driving me nuts.
My first thought was to put a reference to the instance of class b, in my singleton (class A), something like...
sharedInstance.classBReference = self;
..and then declare the singleton in Class D, and then use something like this in class D instance...
[sharedInstance.classBInstance classBInstanceMethod];
But of course as soon as I did..
classB *classBReference;
In the header of my singleton, it game me the "unknown type" which I read about on here, so instead, I put a
#class classB;
above the #interface, and then I was able to declare...
classB *classBReference;
Without an error of unknown type, but in the init method of class B, this...
sharedInstance.classBReference = self;
Still gives me an error of type
"property classBReference not found on objet of type "class A*" (the singleton) did you mean to access ivar classBReference?"
And I have no idea why it's doing that, what's the solution? or is there a better way to do what I'm trying to do?
Dots and Arrows
The "dot notation" is a somewhat recent addition to Objective-C and provides a shorthand notation for accessors. If you have a pointer to an object (or a struct!), you cannot access its instance variables with . but only with ->.
Your line
sharedInstance.classBReference = self;
is exactly the same as
[sharedInstance setClassBReference:self];
The problem is that you don't have any such method -setClassBReference:. In order to set the instance variable, you must instead write
sharedInstance->classBReference = self;
#protected variables
After switching your line with this one, you may (if you haven't made it #public) see the error
Instance variable 'classBReference' is private
In this case, you need to alter your classA interface so that classBReference is declared to be #public. Your list of instance variables in classA should look something like
#interface classA : NSObject
{
//#protected
//(The #protected keyword is optional when at the beginning of the list; instance
//variables are protected by default, which is why you're needing to declare your
//instance variable classBReference to be #public (since classB is not a subclass
//of classA and consequently cannot access its protected instance variables).
//....
//some protected instance variables
//....
#private
//....
//some private instance variables
//....
#public
//....
//some public instance variables
classB *classBReference;
//....
#protected
//....
//some more protected instance variables
//Note that #protected is not optional in order to make the instance variables
//here be protected since they are declared subsequent to the prior #public.
//....
}
//....
#end
Using #properties
The case of classBReference
That being said, it is widely regarded as a better practice to use accessors rather than instance variables in general. In order to do this, you should add a property to your classA interface:
#interface classA : NSObject
{
classB *classBReference;
}
#property classB *classBReference;
#end
and synthesize the classBReference property to access the classBReference instance variable in classA's implementation as follows:
#implementation classB
#synthesize classBReference = classBReference;
The general set-up
The #synthesize is somewhat unclear on account of the fact that we have both an instance variable and a property with the same name. Some clarification is in order. In general, in a class's ("MyObject" in this example) #interface one declares an instance variable ("myVariable" in this example) and a property ("myProperty" in this example).
#interface MyObject : NSObject
{
SomeObject *myVariable;
}
#property SomeObject *myProperty;
#end
In the class's #implementation one has the line
#synthesize myProperty = myVariable.
The result of this code is that, given an instance
MyObject *object = //...
of the class, one is able to write
SomeObject *someObject = //...
[object setMyProperty:someObject];
and
SomeObject *someOtherObject = [object myProperty];
The result of calling -setMyProperty: on the instance of MyObject is that myVariable is set equal to the argument passed into the method--in this case someObject. Similarly, the result of calling -myProperty on the instance of MyObject is that myVariable is returned.
What does it get us?
Without the #property and #synthesize directives, one would have to declare the methods
- (void)setMyProperty:(SomeObject *)myProperty;
- (SomeObject *)myProperty;
manually and define them manually as well:
- (void)setMyProperty:(SomeObject *)myProperty
{
myVariable = myProperty;
}
- (SomeObject *)myProperty
{
return myVariable;
}
The #property and #synthesize provide some abridgment to this code. The amount of code that is generated for you becomes even more beneficial when you use various of the property attributes.
Note: There is more to say about the #property and #synthesize directives. For a start, not only can you write #synthesize myProperty; omitting the variable name, you can omit the synthesizing of myProperty entirely, and the variable names that are used automatically are different from one another in these two cases.
A Bit More on Dot Notation
The dot notation from your question provides another layer of abbreviation. Rather than having to write
[object setMyProperty:someObject];
you are now able to write
object.myProperty = someObject;
Similarly, rather than having to write
SomeObject *someOtherObject = [object myProperty];
you are now able to write
SomeObject *someOtherObject = object.myProperty;
It is important to note that this is just just notation. Though it "kinda looks like" we're doing simple assignment when we "set object.myProperty equal to someObject", that is not the case. In particular, when we execute the line
object.myProperty = someObject;
the method
- (void)setMyProperty:(SomeObject *)someObject
is executed. For this reason, dot notation is a subject of some contention. It is a convenience, but it is important to keep in mind what your code is doing.
The error message tells you the answer. You should define classBReference as property or use classBReference as ivar.
It sounds like you'd be less confused by avoiding the global variable (aka singleton). Give the C a reference to the B when the B creates the C. Give the D a reference to the B when the C creates the D.
If you need to avoid a retain cycle, make the back-references to the B either weak (if your deployment target is at least iOS 5.0) or unsafe_unretained (if your deployment target is earlier than iOS 5.0).
I'm just starting to learn Objective-C, one thing I'm trying to learn is good Property use. I'm currently trying to create some properties with custom setters. This is how far I've gotten:
#interface MyClass : NSObject
#property (nonatomic, assign) int myNumber;
#end
#implementation MyClass
#dynamic myNumber;
- (int)myNumber {
return ???;
}
- (void)setMyNumber:newNumber {
myNumber = newNumber;
// custom stuff here
}
I really just want to implement a custom setter, I'm fine with the getter being default. However, how do I access the variable directly? If I put "return self.myNumber", won't that just call the getter method and infinite loop?
Property access functions are only called when using the x.p notation. You can access the instance variable backing the property with just p (in Objective C, all members have the class instance variables in scope). You can, if you really want, also access via the pointer deference notation ->. So, any of these two:
return p;
return self->p;
However, you needn't use #dynamic here. #synthesize is smart, and will only create defaults if you've not provided them. So feel free to just
#synthesize p;
Which will create the getter, but not the setter in this case.
- (int)myNumber {
return myNumber;
}
I'm coming from C# development and just started to learn Objective-C and Xcode 4.
As far as I understand "#synthesize" is replacing getter/setter methods for properties if you don't need to check/control the values which are being read or written.
But why does Xcode 4 create a instance variable for me automatically?
Wouldn't this be enough:
#synthesize myProperty;
instead of:
#synthesize myProperty = _myProperty;
?
Why would I want to use/have the instance variable instead of the actual property if I don't have/need any getters or setters?
Thanks in advance!
MemphiZ
EDIT:
I understand that #synthesize is replacing getters/setters but what is this part good for: = _myProperty;?
Why would I want to have a instance variable if I could use "myProperty" directly? I would understand using "_myProperty" if the setter for example would check for a condition of the value. If I then want to skip this check I would use _myProperty. But as I use #synthesize I don't have a setter in place that does some check. So why do I have/want an instance variable then?
ANSWER:
See the comments in MattyG's post!
This is a convention used to remind the programmer to access the instance variables through the setters and getters with self. So if you're using:
#synthesize myProperty = _myProperty;
Then to access the variable directly you must write:
_myProperty = something;
To access the variable through it's setter you must write:
self.myProperty = something;
The benefit is that if you forget to access through self. then the compiler will warn you:
myProperty = something; //this won't compile
See this also this Question.
Well, you DECLARE a property's instance variable in the .h file, as well as the property itself. The interface to the property as well as the instance variable it'll use have been established with that... its implementation has not. That's where the #synthesize keyword comes in. It just implements the property for you, so that you don't have to write it out yourself.
Here are ways to declare properties in C#
private int _int1;
public int int1 {
get { return _int1; }
set { _int1 = value; }
}
This is a pretty common piece of code, and C# lets you abbreviate it to avoid having to type the same thing over and over
public int int1 { get; set; }
The difference between these two code segments is that the private variable "_int1" does not exist in the latter, since C# creates a variable internally. The #synthesize keyword is nice because it saves you the hassle of writing down the same code over and over while still allowing you to access the instance variable it's based on.
Edit. It's also important to note that getters and setters do exist in objective C. They just have different names than in C#, where they're labeled get{} and set{}. In objective C, the getter is a method with the same name as its instance variable, and the setter is a method with the word 'set' followed by the instance variable name with the first letter capitalized.
So, lets say you have this in your .h file
int myVar;
...
#property(nonatomic, assign) int myVar;
You can implement getters and setters yourself in the .m file
-(int)myVar {
return myVar;
}
-(void)setMyVar:(int)newVar {
myVar = newVar;
}
or you can just use #synthesize to have the getter and setter written automatically
I'm new to C, new to objective C. For an iPhone subclass, Im declaring variables I want to be visible to all methods in a class into the #interface class definition eg
#interface myclass : UIImageView {
int aVar;
}
and then I declare it again as
#property int aVar;
And then later I
#synthesize aVar;
Can you help me understand the purpose of three steps? Am I doing something unnecessary?
Thanks.
Here, you're declaring an instance variable named aVar:
#interface myclass : UIImageView {
int aVar;
}
You can now use this variable within your class:
aVar = 42;
NSLog(#"The Answer is %i.", aVar);
However, instance variables are private in Objective-C. What if you need other classes to be able to access and/or change aVar? Since methods are public in Objective-C, the answer is to write an accessor (getter) method that returns aVar and a mutator (setter) method that sets aVar:
// In header (.h) file
- (int)aVar;
- (void)setAVar:(int)newAVar;
// In implementation (.m) file
- (int)aVar {
return aVar;
}
- (void)setAVar:(int)newAVar {
if (aVar != newAVar) {
aVar = newAVar;
}
}
Now other classes can get and set aVar via:
[myclass aVar];
[myclass setAVar:24];
Writing these accessor and mutator methods can get quite tedious, so in Objective-C 2.0, Apple simplified it for us. We can now write:
// In header (.h) file
#property (nonatomic, assign) int aVar;
// In implementation (.m) file
#synthesize aVar;
...and the accessor/mutator methods will be automatically generated for us.
To sum up:
int aVar; declares an instance variable aVar
#property (nonatomic, assign) int aVar; declares the accessor and mutator methods for aVar
#synthesize aVar; implements the accessor and mutator methods for aVar
This declares an instance variable in your object:
#interface myclass : UIImageView {
int aVar;
}
Instance variables are private implementation details of your class.
If you want other objects to be able to read or set the value of the instance variable (ivar), you can declare it as a property:
#property int aVar;
This means that the compiler expects to see setter and getter accessor methods for the property.
When you use the #synthesize keyword, you are asking the compiler to automatically generate setter and getter accessor methods for you.
So, in this case the compiler will generate code similar to this when it encounters the #synthesize keyword:
- (int) aVar
{
return aVar;
}
- (void)setAVar:(int)someInt
{
aVar = someInt;
}
By default on the iPhone (and on the 32-bit runtime on the Mac), #synthesize requires an instance variable to be present in order to store the property's value. This ivar is usually named the same as the property, but doesn't have to be, for instance you could do this:
#interface myclass : UIImageView {
int aVar;
}
#property int someValue;
#synthesize someValue = aVar;
Neither #synthesize nor #property are actually required, you can create your own getter and setter methods, and as long as you create them using Key-Value Coding-compliant syntax, the property will still be usable.
The requirement for an ivar to be present as well as the #property declaration is due to the fragile base class limitation of the 32-bit Objective-C runtime on both the Mac and iPhone. With the 64-bit runtime on the Mac you don't need an ivar, #synthesize generates one for you.
Note that there are numerous keywords you can use with your #property declaration to control what sort of synthesized accessor code is created, such as readonly for a getter-only accessor, copy, atomic, nonatomic and so on. More information is in the Objective-C 2.0 Programming Language documentation.
Classes can have instance variables (ivars). These are in the first section, and are only visible to code in that class, not any outside code. I like to prefix them with an underscore to show their internal-ness. In low level terms, the ivars are added as an additional member to the struct that the class you are creating uses internally.
The second declaration, #property, is a declared property. It is not required (except when you are using #synthesize), but it helps other programmers (and the compiler!) know that you are dealing with a property, and not just two methods -setAVar and -aVar, which is the alternative way of doing this.
Thirdly, the #synthesize actually creates the methods to set and access the property from outside the class. You can replace this with your own setter and getter methods, but only do that if you need to, as the built-in ones have some features that you would otherwise have to code yourself. In fact, using the #synthesize aVar = _someVariable; syntax, you can have your property actually reference a differently named instance variable!
Short version:
The #property is just a hint to the compiler and other programmers that you are making a property and not just getter/setter methods. The instance variables are internal to the class, and otherwise cannot be normally accessed from outside it. The #synthesize just creates simple getters and setters for you, to go with your #property, but you can also just code those getters and setters yourself, like any other method.
Class A
#interface myclass : UIImageView {
int aVar;
}
If you declare like this then you can only use this variable within your class A.
But suppose in Class B
A *object=[A new];
object.aVar---->not available
For this you should **declare aVar as a property in Class A**
so class A should look like
Class A
#interface myclass : UIImageView {
int aVar;
}
#property int iVar;
and
.m file
#synthesize iVar;
So now you can use this iVar in another class Suppose B
Class B
#import "Class A.h"
enter code here
A *object=[A new];
object.aVar---->available
means
object.aVar=10;
#interface declares the instances variables of a class in obj-c. You need it to create an instance variable. However the variable is not visible outside the class by default (as the field is by default protected).
#property tells the compiler to specify a particular property accessor (get/set) method. However, you will need to use #synthesize to actually have the compiler generate the simple accessors automatically, otherwise you are expected to create them on your own.
I recently started learning iphone apps. As per my knowledge #property is used in .h file as a setter method and #synthesize in .m file as getter method. In Java we use setter and getter methods, same as Java, in Objective C we use #property and #synthesize.
Please forgive me If u think I mislead you.