I keep seeing things like this in example Objective C code:
_myProp = newValue;
As far as I understand, creating a property myProp will create the actual variable as _myProp, and two accessor methods which are (by default) myProp (the getter) and setMyProp (the setter).
My question is, why do I keep seeing example code that by-passes the accessor methods and gets at the variable directly? Is there any advantage to this?
There are occasions where you don't want to declare a property and instead just use a private ivar.
If, on the other hand, there is a property declaration there should be no reason to directly access the ivar, except in the implementation of the accessors.
Sometimes people want to bypass the side effects of accessors and use the ivar directly. This is usually a sign of an architectural flaw, though.
There are two times that I use the ivar directly.
When overriding the getter or setter. If you use the property self.blah inside the getter or setter it creates an infinite loop.
In the init method of a class.
Related
I was wondering why assigning values to properties in another class causes EXC_BAD_ACCESS. I can't seem to figure out why.
1.) The value being sent into the setter is non-nil;
2.) When trying to assign the value, EXC_BAD_ACCESS happens, the variable is nil;
Using this pattern in both Cocoa and Cocoa Touch applications both causes EXC_BAD_ACCESS, so I don't think it's the platform, but I believe it's the pattern I'm using.
My questions are, is it when the variables are assigned, or is it the way I'm creating the properties?
I have created a dummy project which is seen in the pictures below.
Any help is appreciated.
EDIT: Doing some digging, I changed the name of the setter's variable (not the property name) to firstName__. Basically, the code in the setter for setFirstName:
- (void)setFirstName:(NSString *)firstName__
{
self.firstName = firstName__;
}
Doing this cleared up a little confusion by saying firstName__ (and not self.firstName) is equal to nil, even though in the AppDelegate, the value is non-nil.
Your problem is recursion. In the setter, you are calling the setter method again, and again and again.
When you declare
self.firstName = first name__;
is basically the equivalent of
[self setFirstName:first name__];
So the method is calling itself which doesn't make much sense to do.
You first need to wrap your head around properties and instance variables.
Objective C class instances often contain instance variables that hold values.
Even though it is possible to expose these variables to outside world via #public qualifier, this is not the established convention.
The convention is to have properties, which behind the scenes are a "wrapper" around private instance variable.
Since in Objective C you can only communicate with other objects via messages, to be able to access the values of instance variable you have setter and getter methods that are invoked when you send an appropriate message to the object.
Modern objective C creates instance variable for you implicitly when you declare properties. It is often said that those properties are backed by instance variables.
Normally there is no reason to explicitly implement setters and getters, as the compiler does this for you behind the scenes. (in a same manner, it also creates those instance variables for you)
But if you want to implement setters explicitly, you need to set the instance variable in the setter, not call the setter itself again (via dot notation convention) as I explained above.
Implicitly created instance variables have a naming convention with underscore as prefix. In your case it is
_firstName
When you declare a property called firstName, you also get an instance variable
_firstName
You setter should look like this
-(void)setFirstName:(NSString *)firstName
{
_firstName = firstName;
}
And getter
-(NSstring *)getFirstName
{
return _firstName;
}
Just looking at an example of code which implements a method called bodyMassIndex.
Rather than access the instance variables in the class directly, the idea is that accessor methods are used instead. I'm just not sure whether both setter and getter methods are present here and that's what I need to ask about.
Here is the code:
-(float)bodyMassIndex
float h = [self heightInMeters];
return [self weightInKilos] / (h*h);
What I am really wondering is where is the setter method in this code? I see the getter methods being used, in terms of the two messages heightInMeters and weightInKilos being sent to the instance of the class, but I'm not seeing the setter methods. Is it that the setter methods are not going to be used in the implementation of other methods?
I have seen the setters used in the related main.c file for this program so I know how they get used in terms of setting a value indirectly.
Are setters only used purely outside of the class then?
I really don't like to copy and paste code and ask about it. I'd rather ask questions about code I've written myself that I'm having problems with, but as I am new to accessor methods I haven't any choice this time!
This will (most likely) be the getter for a read only property, because it is computed and there is no backing iVar referenced. heightInMeters and weightInKilos are probably read/write and this is just a little helper, where there would be no point keeping track of it (bodyMassIndex) when it is just the product of two other properties, doing so just invited conflict and errors
The recommended practice is to use property, including private ones through class extension instead of ivar (except in init and dealloc) in the post ARC environment.
Aside from it being a recommended practice, what are the main drawbacks in someone using ivar instead of property? I am trying to convince some folks to make the switch but some have argued ivar works just as well and faster. So I would like to collect good solid arguments rather than giving soft statements such as "it's better, more consistent, etc."
There is no right answer to your question, just opinions. So you'll get varying answers, here's one to add to your collection :-)
Using private properties is is not recommended practice, it is largely a fad. :-)
A public property is part of the encapsulation of the class - how a property (or method) is implemented is not relevant to the user, only the behaviour.
A class does not need to hide how it is implemented from itself!
So the only use cases for private properties is where they provide some behaviour in a convenient way to the implementation of the class, not to hide that behaviour.
A private property with the copy attribute may be convenient if the class is, say, obtaining mutable strings from another class and needs to preserve their current values.
If the class wishes to lazily construct a value if it is needed but keep it after that time then a property can handle that conveniently. Of course a method or function can as well as a property is after all just a method call.
To make the choice think convenience/code design rather than encapsulation as you do for public properties. And most of the time you'll probably just use instance variables, just as you just use local variables.
HTH
There is not much difference in terms of performance. In reality, properties are instance variables with the accessors generated. So the reason why you want to do properties is because the code to generate the KVO notifications and the setter/getter methods are generated to you. So you have less time doing repetitive code on all your classes.
There are a few cases where using a private property is better or required over using an instance variable:
KVO - Since KVO requires getter/setter methods to do the work, you need a property (technically just the methods). Using KVO on a private property probably isn't too common.
Lazy loading or other "business logic" around the value. Using a property with custom setter/getter methods allows you to apply lazy loading and/or other logic/validation around the value.
Access to the value inside a block using a weak reference.
The last point is best covered with an example. As many people know, under certain conditions you can create a reference cycle in a block and this can be broken using a weak reference to self. The problem is that you can't access an ivar using the weak reference so you need a property.
__weak typeof(self) weakSelf = self;
[self.something someReferenceCycleBlock:^{
weakSelf->_someIvar = ... // this gives an error
weakSelf.someProperty = ... // this is fine
}];
Basically, use an ivar if none of these points will ever apply. Use private properties if any of these may apply over the lifetime of the class.
So in some of the codes I see, they access an objects ivar directly instead of using accessors . What are the advantages of using them instead of accessors?
So how would this
thing = object->ivar
differ from this?
thing = object.ivar
Thanks.
First let me say, I totally loathe the Objective-C dot notation. It sacrifices understandability for brevity and that is a bad thing. In fact, the other two answers here both show evidence of the kind of confusion dot notation introduces.
Having got the rant out of the way, I'll now try to answer the question.
Under the hood, Objective-C objects are implemented as pointers to C structs. This is why
obj->ivar
sometimes works. Given that it's a C struct
(*obj).ivar
should also work exactly as you would expect for C. Having said that, you can make ivars private or protected, in which case using the above outside a scope where they are visible will cause a compiler error.
The dot operator when applied to an Objective-C object (which is a pointer don't forget) has a totally different meaning. It's syntactic sugar for sending an accessor message to the object meaning that:
foo = obj.property;
obj.property = foo;
is identical in effect to
foo = [obj property];
[obj setProperty: foo];
That is all there is to dot notation. If you go through your code changing all instances of the first form to instances of the second form, you have done everything the compiler does wrt dot notation.
In particular
you do not need a declared #property to use dot notation. You can declare the set and get accessors in the traditional way as Objective C methods, although it is definitely best practice to use #property declarations for things that are logically properties.
you do not need a backing instance variable. There's no reason why your getters and setters can't calculate values.
Given the above, the major difference between obj->ivar and obj.ivar is that the former modifies the ivar directly and latter invokes an accessor, this means that the latter can do any memory management stuff needed (retains, releases, copies etc) and can also invoke key value observing.
This is one thing with a huge difference between c/c++ and objective-c.
In C/C++ the . accesses the variable directly and the -> accesses the variable if it's a pointer to the variable, so basically it is the same.
In Objective-C the . is a shortcut to access the property using the setter and getter function and it is always using those functions. You can't access ivars with it if there is no property with that name.
Some say it's "dirty" to allow direct access to the variables. If more people work on the code it's "cleaner" to use accessors because it might be easier to debug where variables are changed since you can always break in the setter.
You can even do "bad" things with it, like:
NSArray *array = [NSArray alloc] init];
int count = array.count;
array.release;
this will technically work, because the array.release is a shortcut for [array release] but it is bad style to use . for other things then properties.
The advantage of properties is that they call methods that work with your ivars, in stead of calling the ivars directly, so you can do things like this:
-(void)setFrame:(CGRect)frame
{
if([self frameIsValid:frame])
{
if(self.flipsFrames)
{
frame.size = CGSizeMake(frame.size.height,frame.size.width);
}
[super setFrame:frame];
[delegate viewSubclass:self ChangedFrameTo:frame];
}
}
Four advantages shown here are:
The possibility to override
The possibility to check a given value
The possibility to alter a given value (use with caution)
A way to react to calls
Another advantage:
-(NSInteger) amountOfMinutes
{
return amountOfSeconds * 60;
}
You can use 1 ivar for multiple properties, saving memory and preventing/reducing redundancy, while keeping useful different formats.
There's not really an advantage to using ivars, except when you don't want to use a property so your class is more encapsulated. That does not make it impossible to reach, but it makes it clear it isn't supposed to be reached.
All ivars are private. There is no way to access them directly from outside the object. Therefore, both of your code samples are equivalent, in ObjC terms.
When you call object.ivar, what you are really doing is calling object's ivar selector. This may be either a getter method that you wrote yourself, or more likely, a synthesized getter method that you created with #synthesize.
thing, however, is an ivar. Your code would be calling the ivar selector on object and assigning the result directly to your instance's thing ivar.
If you had instead written it as self.thing = object.ivar, then you would be using your instance's setter method to assign to thing.
Some of the advantages of using accessors (specifically, synthesized properties) in ObjC are KVO/KVC compliance; better concurrency support; access control (readonly, readwrite); as well as all of the advantages that accessors give you in any other OO language.
I understand that one version directly accesses the instance variable and the other calls it's accessor method.
If self.classVariable = sandwich;
&
If classVariable = sandwich;
do the same thing.
Can someone explain the point of the extra typing?
In Objective-C, self.property is property access, not direct instance variable access. It is syntatic sugar for [self property] or [self setProperty:], and thus has the semantics of a message. Modern Objective-C runtime can synthesize a backing instance variable (of the same name as the property), but you may back a property with an instance variable with a different name or none at all. In other words,
self.property = foo;
id bar = property
and
property = foo;
id bar = property;
are not at all the same thing.
It's generally a bad idea to mix direct and property access (with the exception that you should be accessing ivars directly in -init and -dealloc methods) because you will easily run afoul of memory management rules.
The extra typing is to protect the code from future changes, in case a variable is named (in scope) equal to the class member.
It is also considered good practice (in some circles) to include Self when referring to members in the class to be unambiguously clear where it comes from which in some ways helps quicken comprehension of the code.
For Objective-C specifically, there is another difference as noted here http://answers.oreilly.com/topic/1193-calling-self-object-rather-than-calling-the-object-directly-in-objective-c/
The SELF.X notation goes through the accessors generated by the #synthesize directive, whereas X directly bypasses them.
If you go through the accessor you can set breakpoints there. Handy sometimes. Also things like retain/copy properties won't work if you don't go through the accessor.