Getter and Setter Explained? - objective-c

I am just learning OOP from a book I picked up (Big Nerd Ranch), and it just went through the getter and setter chapter. I would just like to clarify I understand what I have just done. Instead of creating a method to set the value of an instance, and then another method to extract the value and display it, I create use the #property and #synthesize syntax to define both methods.
Instead of doing this:
-(void) setHeightOfObject:(int)h;
-(void) setWeightOfObject:(float)w;
-(int) heightOfObject;
-(float) weightOfObject;
and defining it like this:
- (int)heightOfObject
{
return heightOfObject;
}
- (void)setHeightOfObject:(int)h
{
heightInMeters = h;
}
- (float)weightOfObject
{
return weightOfObject;
}
- (void)setWeightOfObject:(float)w
{
weightOfObject = w;
}
I would do this with getter and setters in the .h file:
#property int heightOfObject;
#property float weightOfObject;
And then go to my .m file and link it:
#synthesize heightInMeters, weightOfObject;
This then gives me the ability to set the value of my object, and then get it if I need it printed? I know this is an important concept and I want to make sure I have the proper grasp of it.

You are correct. The #synthesize essential expands out to the implementation you wrote while compiling.
Since writing getters and setters is boring and repetitive (and most objects have a bunch of properties you'd want getters and setters for) having this little shortcut makes you spend less time on boilerplate code and more time implementing something interesting.
If you'd like more detailed information about objective-c's properties, you can have a look at the programming guide (although this might be somewhat unnecessarily detailed for you at this point).

There are two parts to what you are achieving by using #property and #synthesize.
#property tells the compiler that it should allow you to use dot syntax to call the accessors of heightOfObject and weightOfObject. So doing this
int height = myObject.heightOfObject;
myObject.weightOfObject = 10;
becomes legal code and is exactly equivalent to this:
int height = [myObject heightOfObject];
[myObject setWeightOfObject:10];
You can use #property without #synthesize, in which case you must implement the accessors exactly as you have done in your question.
Using #synthesize tells the compiler that it should generate the accessors for you and it will also generate the instance variables themselves if your runtime supports it (e.g. on iOS and 64-bit OS X).

Property and synthesise were introduced in Objective C 2.0 in order to provide a straightforward way to create getters and setters.
Check this link it will be of help:
http://cocoacast.com/?q=node/103

You not only get getters and setters. You also get a neat syntax: self.heightOfObject which you can assign to or read from.
#property has a lot of settings though so you might want to read in detail. In particular you can control whether you need both read and write access or only one of them.

Related

Objective C assignment calling setter?

I have a field:
#interface SomeClass : NSObject
#property(nonatomic, nullable) BOOL questionCreated;
#property(nonatomic, nullable) NSString question;
If I create a setter for question like:
-(void)setQuestion:(NSString)question {
_question = question;
_questionCreated = YES;
}
And then in another file suppose I have an instance of SomeClass called someClassInstance.
If I do something like:
someClassInstance.question = "manually set question"
to my surprise I see that someClassInstance.questionCreated now also has the value YES, which makes me believe it calls the setter directly if I do someClassInstance.question. Why is this and how I can forcefully only set one of the field?
This line of code:
someClassInstance.question = #"manually set question";
is the same as this line of code:
[someClassInstance setQuestion:#"manually set question"];
And by "the same," I mean the former is converted into the latter at compile time. This is what "dot notation" means in Objective-C.
(Side note: when this syntax was added to ObjC in 2007 it was pretty controversial, specifically because it causes the kinds of confusion that you've run into. I was not a fan at the time. Like most folks, however, I've grown very accustomed to the sugar and it is easier to type, so you get used to it. But your confusion is not surprising.)
As a rule, external objects should not be concerned about the internal details of the setter. If they are, something is incorrectly designed (I would probably rename setQuestion to something else).
But another approach is to provide a direct setter. This is most often prefixed "primitive" like:
- (void)setPrimitiveQuestion:(NSString *)question {
_question = question;
}
And then you build setQuestion on top of that:
- (void)setQuestion:(NSString *)question {
[self setPrimitiveQuestion: question];
self.questionCreated = #YES;
}
To your actual question, yes it is possible to do exactly what you're suggesting. It is generally bad form, but if you really need it you can reach in and modify ivars directly:
someClassInstance->_question = #"...";
But don't do this unless you really know what you're doing.

recursive issue with getter ios objective c

I have this property:
#property (nonatomic, getter = getSolutionsCount, setter = setSolutionsCount:) NSInteger solutionsCount;
and implementation
- (NSInteger)getSolutionsCount {
return self.solutionsCount;
}
and I get EXC_BAD_ACCESS on this method - (NSInteger)getSolutionsCount.
What am I doing wrong here?
dot syntax is basically a shortcut for calling the getter. You have infinite recursion in your getter method.
What you need to do is return the instance variable directly:
- (NSInteger)getSolutionsCount {
//latest xcode makes variables with _property name automatically
return _solutionsCount;
//older versions of xcode or having written #synthesize solutionsCount
//will necessitate
//return solutionsCount;
}
Also just FYI objective-c convention is to have the getter method be defined as just the variable name. A getter which is the same as the property name is assumed if you don't write a getter in the property declaration
EDIT:
also i'm assuming this isnt the whole implementation for your getter because if it is let the compiler make it for you automatically, you don't need to write anything. (or by writing #synthesize propertyName = _propertyName in your implementation block with older versions of xCode)
The line self.solutionsCount is translated to [self getSolutionCount]. You are making a recursive call.
If you simply want to return the synthesized ivar then don't even implement this method. But if you do then simply call return _solutionCount;.
The problem is that self.solutionsCount is identical to [self getSolutionsCount], so your getter is directly recursive. You probably want to access the underlying ivar directly, to do so use self->_solutionsCount. Or, if you prefer not to explicitly use self, simply _solutionsCount.
There are several problems here:
According to the naming convention getters should not start with get. To read the value you need to use self.solutionsCount. Hence, you do not need to specify the name of the getter method in the property declaration.
You do not need to specify the name of the setter for it will be automatically generated.
The property should look like this:
#property (nonatomic, assign) NSInteger solutionsCount;
You do not need to write a custom getter implementation to make it work. Ask the compiler to synthesize the methods for you:
#synthesize solutionsCount;
If you want to have a direct access to the instance variable, ask compiler to sythesize it for you:
#synthesize solutionsCount = _solutionsCount;
Read objective-c and naming convention docs first. They will help enormously.
Good luck!

Where are the synthesized ivars stored?

I've been reading up on the automatically synthesized ivars. My question is, "WHere are automatically they allocated?" I would have expected them to be part of self, so that I could see them in the debugger, but it seems that the only way I can see them is by invoking the accessor method (via the gdb 'po' command). Isn't there space in the class/object's struct (as there would be for an explicitly declared ivar)?
(Is there a description of the in-memory representation for a modern Objective-C object?)
Being a C guy, it makes me very uncomfortable to not to be able to see where everything is. :-P
Looks like this will tell you:
How do automatic #synthesized ivars affect the *real* sizeof(MyClass)?
I am a C guy at heart too. Why bother using these auto generated ones? I like looking at a class and seeing what it holds onto in terms of data.
Interesting: Neat how they took the 64 bit change to make things better.
http://www.sealiesoftware.com/blog/archive/2009/01/27/objc_explain_Non-fragile_ivars.html
They are added to the objective-c object (which is a C structure) no different to a regular ivar, so for example:
#interface TestObject : NSObject {
}
#property (nonatomic, assign) int theInt;
#end
#implementation QuartzTestView
#synthesize theInt;
#end
You can refer to theInt ivar directly (not through property accessors) either:
- (void)someMethod {
theInt = 5;
}
OR
- (void)someOtherMethod {
self->theInt = 10;
}
See http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html - using the modern runtime an instance variable "will be synthesized for you". It can be nice to add a variable yourself instead though (so that you can see it when debugging in self), however you have to be careful not to do direct assignments to the instance variable for retain or copy based properties.

#property and #synthesize in objective-c

While I was playing and figure out how things work in https://github.com/enormego/EGOTableViewPullRefresh I found mysterious of #property and #synthesize. Here is the code I mentioned
EGORefreshTableHeaderView.h
#interface EGORefreshTableHeaderView : UIView {
id _delegate;
EGOPullRefreshState _state;
UILabel *_lastUpdatedLabel;
UILabel *_statusLabel;
CALayer *_arrowImage;
UIActivityIndicatorView *_activityView;
}
#property(nonatomic,assign) id <EGORefreshTableHeaderDelegate> delegate;
EGORefreshTableHeaderView.m
#synthesize delegate=_delegate;
I have read this http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html and from what I understand is it create new name for _delegate which is delegate. (Am I right with this understanding ?)
But I still doesn't understand why they have to make thing complicated with those #synthesize = directive.
How complicated is it, really? It's just a bit of syntax that lets you specify the ivar that you want to use to back the property for which you're telling the compiler to create accessors. If they didn't provide this or something equivalent, then you'd always have to have your property names match your ivar names, and there are reasons that you might not want that.
If you don't need to name your ivars differently, then you don't have to bother with specifying the ivar name. In fact, you don't have to create ivars at all for your properties... if you don't, the compiler will create them for you.
Update: As of the middle of 2013, LLVM defaults to synthesizing accessors for properties, so in most cases you no longer need to specify #synthesize at all. The one case where you would still use it is when you want to back the property with a different instance variable than the one that the compiler would generate for you. Also, the default name for the ivar that backs a property will be the property name prefixed with an underscore. So, the code in the OP's example could be simplified by deleting the lines:
id _delegate;
and:
#synthesize delegate=_delegate;
I've removed my previous advice against using an underscore prefix since it clearly disagreed with the current fashion and default behavior of the compiler. As far as I know, it's still poor form to use an underscore prefix for your method names, however.
Also, it has come to my attention that at least one person interpreted the first line of my response, "How complicated is it, really?" as condescending. I hope that was only one person's impression -- I definitely didn't intend any condescension, but was only trying to frame my response around the OP's assertion that the #synthesize xxx=_xxx; directive makes things complicated. There's a lot to absorb when you're starting out; hopefully the new "synthesize by default" behavior will reduce the burden for newcomers.
You are right, using
#synthesize foobar=_foobar;
is a bit pointless in most cases , but at an abstract level it does allow you to return the value of some other variable entirely. As in ...
#synthesize foobar=fluffybunny;
Lets you get or set the value of fluffybunny each time you use the accessor .foobar
However in terms of the#synthesize complexity , would you rather write
-(void)setFoobar:(id)aobject {
[self willSetValueForKey:"foobar"];
id old = foobar;
foobar = [aobject retain];
[old release];
[self didSetValueForKey:"foobar"];
}
-(id)foobar {
[self willAccessValueForKey:"foobar"];
id obj = [self primitiveValueForKey:#"foobar"];
[self didAccessValueForKey:"foobar"];
return obj;
}
Or
#synthesize foobar;
Thats not particularly well written as ive forgotten how to do them well but the #synthesize directive stops you having to write accessors so many times. It one one of the things that sucked heavily about Obj-C 1.0.
Free code , dont knock it.

Objective-C synthesize property name overriding

I am trying to understand the purpose of the synthesize directive with property name overriding. Say that I have an interface defined as follow:
#interface Dummy ... {
UILabel *_dummyLabel;
}
#property (retain, nonatomic) UILabel *dummyLabel;
And in the implementation file, I have:
#synthesize dummyLabel = _dummyLabel;
From what i understand, "dummyLabel" is just an alias of the instance variable "_dummyLabel". Is there any difference between self._dummyLabel and self.dummyLabel?
Yes. self._dummyLabel is undefined, however _dummyLabel is not.
Dot syntax expands out to simple method invocations, so it's not specific to properties. If you have a method called -(id)someObject, for example in the case of object.someObject, it will be as if you wrote [object someObject];.
self.dummyLabel //works
self._dummyLabel //does not work
dummyLabel //does not work
_dummyLabel //works
[self dummyLabel]; //works
[self _dummyLabel]; //does not work
Your understanding is incorrect. dummyLabel is the name of the property, and is not an alias for the instance variable - the instance variable is only called _dummyLabel. So the following holds for an instance of Dummy called myObject:
[myObject dummyLabel] works
myObject.dummyLabel works
[myObject _dummyLabel] fails
myObject._dummyLabel fails
myObject->dummyLabel fails
myObject->_dummyLabel depends on the visibility of the ivar (#public, #private, #protected)
[myObject valueForKey: #"dummyLabel"] works
[myObject valueForKey: #"_dummyLabel"] depends on the implementation of +accessInstanceVariablesDirectly (i.e. it will work in the default case where +accessInstanceVariablesDirectly returns YES).
The advantage of having another name
for the ivar than for the property is
that you can easily see in the code
when you are accessing one or the
other - Andre K
I'm not able to find a 'comment' button so I'm having to post as an 'answer'.
Just wanted to expand on Andre's comment - by knowing when you are using the synthesized properties vs the vanilla variable, you know (especially in case of setters) when a variable is being retained/copied/released automatically thanks to your nice setter, vs being manipulated by hand.
Of course if you are doing things right, you probably don't need the help of a setter to retain/release objects properly! But there can be other scenarios too where referring to your ivars as self.ivar instead of _ivar can be helpful, such as when you are using custom setters/getters instead of the default synthesized ones. Perhaps every time you modify a property, you also want to store it to NSUserDefaults. So you might have some code like this:
#interface SOUserSettings : NSObject {
BOOL _autoLoginOn;
}
#property (nonatomic, assign) BOOL autoLoginOn;
#end
#implementation SOUserSettings
#synthesize autoLoginOn = _autoLoginOn;
- (void)setAutoLoginOn:(BOOL)newAutoLoginOnValue {
_autoLoginOn = newAutoLoginOnValue;
[[NSUserDefaults standardUserDefaults] setBool:_autoLoginOn forKey:#"UserPrefAutoLoginOn"];
}
#end
Note: This is just illustrative code, there could be a thousand things wrong with it!
So now, in your code, if you have a line that says _autoLoginOn = YES - you know it's not going to be saved to NSUserDefaults, whereas if you use self.autoLoginOn = YES you know exactly what's going to happen.
The difference between _autoLoginOn and self.autoLoginOn is more than just semantic.
I don't see any big advantage of
renaming _dummyLabel to dummyLabel
In some ObjC runtimes you have a hard time making instance variables invisible to users of the class. For them sticking some prefix (or suffix) on your instance variables can make it clear (or more clear) that you don't want anyone messing with your variables. However you don't want that gunk on your public functions. This lets you get it off.
It could also be useful if you need to maintain an old interface with one set of names at the same time as a new set of APIs with a new set of names (setLastname vs. setSurname).
Old post, but I think its important to mention, that it is recommended to access variables via getters and setters (so, with dot notation). Accessing a field directly (_ivar) is strongly recommended only when initializing it.
There is some good Apple's article:
https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html
Last paragraph:
You should always access the instance variables directly from within
an initialization method because at the time a property is set, the
rest of the object may not yet be completely initialized. Even if you
don’t provide custom accessor methods or know of any side effects from
within your own class, a future subclass may very well override the
behavior.