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.
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;
}
I was wondering what exactly are the differences between using the (get) accessor for reading the value of property and directly using the iVar?
Say I have a class which declares a property:
#interface Foo : NSObject
#property (strong) NSString *someString;
#end
And in the implementation I'm using it. Are there any differences between the following two lines:
someLabel.text = self.someString;
someLabel.text = _someString;
For set accessors it's clear. Afaik for strong properties the accessor takes care of retain and release (an interesting 'side question' would be if ARC changes that, i.e. does setting the iVar directly [assuming it's not an __weak iVar] also retain and release correctly using ARC), also KVO requires the use of accessors to work properly etc. But what about getters?
And if there's no difference, is there one way considered best practice?
Thx
As you know, calling self.someString is really [self someString]. If you chose to create a property then you should use the property. There may be other semantics added to the property. Perhaps the property is lazy loaded. Perhaps the property doesn't use an ivar. Perhaps there is some other needed side effect to calling the property's getter. Maybe there isn't now but maybe this changes in the future. Calling the property now makes your code a little more future proof.
If you have an ivar and a property, use the property unless you have explicit reason to use the ivar instead. There may be a case where you don't want any of the extra semantics or side effect of the property to be performed. So in such a case, using the ivar directly is better.
But ultimately, it's your code, your property, your ivar. You know why you added a property. You know any potential benefits of that property, if any.
I think this what you are looking for. Why use getters and setters?
There are actually many good reasons to consider using accessors rather than directly exposing fields of a class - beyond just the argument of encapsulation and making future changes easier.
Here are the some of the reasons I am aware of:
Encapsulation of behavior associated with getting or setting the
property - this allows additional functionality (like validation) to
be added more easily later.
Hiding the internal representation of the
property while exposing a property using an alternative
representation.
Insulating your public interface from change -
allowing the public interface to remain constant while the
implementation changes without effecting existing consumers.
Controlling the lifetime and memory management (disposal) semantics
of the property - particularly important in non-managed memory
environments (like C++ or Objective-C).
Providing a debugging
interception point for when a property changes at runtime - debugging
when and where a property changed to a particular value can be quite
difficult without this in some languages.
Improved interoperability
with libraries that are designed to operate against property
getter/setters - Mocking, Serialization, and WPF come to mind.
Allowing inheritors to change the semantics of how the property
behaves and is exposed by overriding the getter/setter methods.
Allowing the getter/setter to be passed around as lambda expressions
rather than values.
Getters and setters can allow different access
levels - for example the get may be public, but the set could be
protected.
I am not a very experienced person to answer this question, even though I am trying to give my views and my experience by seeing source code which is around 10yrs older.
In earlier codes they were creating ivars and property/synthesise. Nowadays only property/synthesise is used.One benefit I see is of less code and no confusion.
Confusion!!! Yes, if ivars and its property are of different name, it does create a confusion to other person or even to you if you are reading your own code after a while. So use one name for ivar and property.
By using property KVO/KVB/KVC are handled automatically, thats for sure.
#property/#synthesise sets your ivar to 0/nil etc.
Also helpful if your subclass contains same ivar.
For mutable objects Dont make properties.
When using Objective-C properties can you stop creating instance variables altogether or do explicit instance variables (not the ones synthesized by the properties) still serve a purpose where properties would be inappropriate?
can you stop creating instance variables altogether
No, you can't (in a sense). What you can do is stop declaring them if you have properties. If you synthesize a property and you haven't declared the instvar, it will get declared for you, so you are creating an instance variable, just not explicitly.
do they still serve a purpose where properties would be inappropriate?
It used to be the advice to create properties for everything because having synthesized properties does almost all of the retains and releases for you. However, with ARC that reason for using properties to wrap the memory management has gone away. The advice now (for ARC) is, I believe, use properties to declare your external interface, but use direct instance variables where the variable is part of the object's internal state.
That's a good reason to adopt ARC: properties revert to their true purpose only of being part of the class's API and it's no longer necessary to use them as a hacky way to hide memory management work.
Edit
One more thing: you can now declare instance variables in the #implementation so there is now no need to leak any implementation details in the #interface. i.e.
#implementation MyClass
{
NSString* myString;
}
// method definitions
#end
And I'm pretty sure it works in categories too. - see comment below
I recommend declaring everything as properties and avoiding manual ivars altogether. There is no real upside to manually creating ivars. Declare public properties in your header #interface, declare private properties in a private class extension in your .m file.
To some of JeremyP's points, internal use of accessors still has significant value under ARC, even though memory management is no longer a significant concern. It ensures that KVO works properly, subclasses better, supports custom setters (particularly for things like NSTimer), supports custom getters (such as for lazy instantiation), etc. It is exceedingly error-prone to have a mix of accessors and ivars. It's far too easy to forget which you need to access in which way. Consistency is the hallmark of good ObjC.
If you absolutely must declare an ivar for some reason, then you should do it in the #implementation block as JeremyP notes.
UPDATE (Oct-2013):
Apple's guidance (From Programming with Objective-C: Encapsulating Data):
Most Properties Are Backed by Instance Variables
In general, you should use accessor methods or dot syntax for property access even if you’re accessing an object’s properties from within its own implementation, in which case you should use self:
...
The exception to this rule is when writing initialization, deallocation or custom accessor methods, as described later in this section.
This question was addressed before here
When you use synthesize the instance variables are handled and instantiated for you. If you're using Lion with the new version of XCode also take a look at the various properties in ARC in Transitioning to ARC
you can always access properties from outside. So if you want a variable only to be read from inside a class you still have to declare a iVar. Also accessing a public ivar with object->ivar is slightly faster than using a method-call.
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 have searched many questions on ObjC accessors and synthesized accessors to no avail. This question is more of a "help me settle an issue" question; I don't expect one answer, but I'm rather looking for experts to weigh in on the argument.
In a Cocoa Touch class, I would write some code like this (where soundEffects is a synthesized NSArray property):
id foo = [self.soundEffects objectAtIndex:1];
A colleague asked me to explain why the above is any better than this line:
id foo = [soundEffects objectAtIndex:1];
Well, functionally, it's no different.
My arguments for the former are as follows:
self.soundEffects tells every other coder working on the code that this is an iVar, not a locally scoped variable.
If we ever needed to, we could put custom logic in the soundEffects getter accessor.
For no concrete reason, it "feels" like the right thing to do after working in Obj-C for a year.
He accepts arguments #1 and #2 as valid, but also gives the counterpoint:
Isn't this just code bloat?
Shouldn't a class be allowed to talk to its own iVars directly without having to call a method (the getter) on itself?
Any takers?
I have personally settled on using an underscore prefix for ivars, and this kind of synthesize
#synthesize name = _name;
That way I don't mix them up. The major issue with not using self is that this code
_name = ...
is very different from
self.name = ...
When the #property uses the retain option. The first does not retain the object, and the second calls the synthesized setter that retains.
The only time it makes a big difference is with assigning, so I tend to use self. all of the time so I make sure I do it on assigns.
Your point 1 is not quite right: self.soundEffects is not an ivar, although it may happen to give you something which is -- as it does in the case of your synthesized NSArray, at the moment.
This in turn implies that your point 2 is the crux of the matter -- if you route all access through the accessor, then everything is nicely encapsulated and you're free to modify the implementation later without having to worry about side effects.
It's also good practice for when you use the mutator, so you maintain consistent memory management.
For the most part, I'd say it's advisable to route through self.property for everything that is a property, and restrict direct ivar access to things which are strictly internal. However, I'll admit that in some cases -- especially for things that don't use retain/copy semantics -- it can be more of a style preference.
using something like self.variable = nil makes the variable go through its setter and therefore gets memory managed for free. if you just use variable = nil for instance in a dealloc method, it will cause a leak since it is not actually going through the synthesized setter for the variable and decreasing the retain count. See this post memory leak with self.
For this reason, it is advisable (i believe) to always use self. when dealing with instance variables that you own as far as memory management is concerned.
self.soundEffects sets/gets the instance variable through the setter/getter, and hence if we want to do some custom operations when their value changes, that logic can go in their getter/setter.
Also as per ios 6, the ivar corresponding to
#property (nonatomic)NSArray *propertyName;
will be _propertyName
so i guess you cant use id foo = [soundEffects objectAtIndex:1]; anymore.Not sure though.Instead you should use id foo = soundEffects[1];