Difference between using self.variable and _variable when init these variables [duplicate] - objective-c

This question already has answers here:
Difference between self.ivar and ivar?
(4 answers)
When should I use the “self” keyword?
(6 answers)
Closed 8 years ago.
I know instance variable and property. I often see people init a UILabel like this
self.label = [[UILabel alloc] init]; //and
_label = [[UILabel alloc] init];
So, what's the difference between using self.label and _label to set a object?

The difference is simple: Using self.label = [[UILabel alloc] init] will actually invoke the method [self setLabel:[[UILabel alloc] init]], and using _label = [[UILabel alloc] init] will directly assign the value to the instance variable.
In practice what this means is that using the dot syntax is usually the best as the method invoked probably handles a lot of stuff for you, including:
Memory management: For example, if you declare a property with attribute 'strong' or 'retain', then the method invoked should retain the object assigned.
Key-Value Coding notifications: Maybe the class is key-value coding compliant for the property, which means the invoked method will notify the changes to observer objects.
Why would you not use the dot syntax? There are two potential reasons:
To avoid side effects: A good practice is to not use the dot syntax inside an initializer method. This is because we want to assign the value but don't want the other side effects of the invoked method for safety reasons.
Performance: This is probably rare, but maybe you are trying to implement a method with high performance and using instance variables directly can save the cost of invoking a method.
If you want to know more, I recommend reading this iOS guide which describes in more detail the ideas I mention here.

The difference is that:
the names with _variable are instance variables.
self.variable is calling a getter method on your object.
In your example, the instance variables are automatically generated and you don't need to synthesize your properties either.
The real important difference in your example comes into play if you are not using ARC-
self.variable will retain an object for you if you mark the property with retain or strong _variable does not address memory management at all

In your example, self.label would call the getter method 'label' on self -- this is equivalent to calling [self label]. _label is the backing store for the class instance property -- i.e. an instance variable, no different than accessing a standard variable directly. There is no getter method wrapped around it.
The difference is very, very important, because you are able to override the getter/setter methods for properties. You may wish to do this, for e.g., if you would like to bundle some behavior change with the state change of the variable. Calling the getter or setter maintains this behavior. Calling the getter also retains the variable.
Basically, unless you know why you're preferring to class _label in any particular instance, stick with the getter self.label. One case where you may want to use _label is during initialization, where you need to set a happy default w/o behavior the getter may bring with it.

The difference is that using _label is accessing the instance variable (ivar for short) directly, where as using self.label is actually calling [self setLabel:[[UILabel alloc] init]];.
Calling the setLabel: method does other things, such as possibly retaining the variable (depending on how the property was declared), but can also trigger other side effects as set up in your setLabel: method. Those side effects could be something like data validation, or could perhaps sync that value to a server.

Related

Self contains Self property [duplicate]

This question already has answers here:
What is the purpose of the -self method in NSObject-conformant classes?
(3 answers)
Closed 8 years ago.
I was messing around with Objective-C and I stumbled upon something strange. The following code compiles and works the way I want it to.
self.scrollView.delegate = self.self.self.self.self;
// equivalent to = self;
Why does this compile? Is it the case that self is a property of an object. If so, I have never seen self declared as a property. I thought self referred to the instance of the class you are creating.
Let me turn this around Why shoudn't it compile nor work as expected?
self is a property of NSObject. It always points to the object itself. Every object inheriting from NSObject has it.
As you say, self refers to the instance. Well, it is not only valid in the context of creating instances. It is always there. And it is very helpful.
[self myProperty] or self.myProperty refers explicitely (laugh more or less explicitely but it does) to the getter (or the setter) of the property myProperty while just typing myProperty within a method refers directly to the property without passing the getter.
Another example is someOjbect.delegate = self; or so.
So, as self alsways refers to an object, to the very object, it has a self property that refers to the very object which has a self property ...
BTW, classes are objects in Objective-C that inherit from Class. In the context of a class, i.e. in class methods, it refers to the class object of the very class. You can play the same game there. If you start off with an instance, then you can play the game with the class property.
self.class.class.class == [self class].self.class.self
should evaluate to YES. (Well, I never tried that myself. If you actually try it and find this wrong, then please let me know)
self is a method in the NSObject protocol. It returns the object it is called on, it is rather pointless.
This is distinct from the local variable self, which within a method refers to the object the method was called on.
Both the method and the local variable apply to class objects as well as standard instances, so a class method has a self local variable and a class object a self method.

objective C underscore property vs self

I'm was playing around with the standard sample split view that gets created when you select a split view application in Xcode, and after adding a few fields i needed to add a few fields to display them in the detail view.
and something interesting happend
in the original sample, the master view sets a "detailItem" property in the detail view and the detail view displays it.
- (void)setDetailItem:(id) newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
i understand what that does and all, so while i was playing around with it. i thought it would be the same if instead of _detailItem i used self.detailItem, since it's a property of the class.
however, when i used
self.detailItem != newDetailItem
i actually got stuck in a loop where this method is constantly called and i cant do anything else in the simulator.
my question is, whats the actual difference between the underscore variables(ivar?) and the properties?
i read some posts here it seems to be just some objective C convention, but it actually made some difference.
_property means you are directly accessing the property.
self.property means you are using accessors.
In your case, in the setter method you are calling it, creating a recursive call.
In the course of your experiment, you've set up an endless loop which is why the simulator goes non-responsive.
Calling self.detailItem within the scope of setDetailItem: calls setDetailItem: recursively since your class implements a custom setter method for the property detailItem.
I would refer you to the Apple documentation on declared properties for the scoop on properties, ivars, etc; but briefly, declared properties are a simplified way of providing accessor methods for your class. Rather than having to write your own accessor methods (as we had to do before Objective-C 2.0) they are now generated for you through the property syntax.
The properties are basically a way of the compiler to generate a setter and getter for a given instance variable.
So when you use something like:
id detailItem = self.detailItem;
what you are doing under the hood is:
id detailItem = [self detailItem];
Same for:
self.detailItem = otherDetailItem;
would be:
[self setDetailItem:otherDetailItem];
So when you write the setter yourself.. you get in an infinite loop since you access the method itself in itself.
You can freely make use of the 'self.' notation in your class, just not when you're overriding the setter or accessor because of the mechanism I described above.
Cases in a class where I use the . notation over simply accessing the ivar is when I change the value, you never know inside your class what needs to happen when you change the value. do you have something in terms of a status that should notify some delegate that a status changed? Usually this is not the case, however, just by using the . notation you are making sure that in the future you won't have to refactor some code if you did decide to do some magic in your setter method.
I'll make an example (without ARC enabled):
#property (nonatomic, retain) NSNumber* number;
If you don't synthesize it, you can access it this way:
self.number= [NSNumber numberWithBool: YES];
This case the number is retained.If instead you synthesize it and don't use the property:
#synthesize number;
Later in the file:
number=[NSNUmber numberWithBool: YES];
You haven't used the property, so the number is not retained.That makes a relevant difference between using accessors and synthesized properties.

#property or init to set instance variables

While doing my project I was wondering if I should set my instance variables for a viewcontroller through the viewcontrollers #synthezied properties or creating a new init function that sets the instance variables when the init it called.
For me, it seems like setting the instance variables using the #properties are cleaner.
What do you think?
I dont use nibs or storyboards...
Synthesizing the properties just saves you from the trouble of writing setters and getters. Just using #synthesize does not initialize your properties. You should definitely initialize them - either in -init or when declaring them.
I'd go for designated initialiser approach as in set instance variables that then can be used via #synthesized properties. Initialising view controller and then setting its properties leave the object in an inconsistent state.
Designated initializer:
MyViewController * viewController = [[MyViewController alloc] initWithParam1:#"foo" param2:#5];
// now viewController is consistent as presumably it has all properties set
Setting properties via setters:
MyViewController * viewController = [[MyViewController alloc] init];
// here viewController is inconsistent as it does not have default properties set
[viewController setParam1:#"foo"];
[viewController setParam2:#5];
// only here viewController is consistent and can be used normally
Depending on implementation of your initialisers you may set default values for properties without passing them as params to initialiser too, so my second example may be faulty if init silently sets param1 to #foo and param2 to #5.
In general your designated initialiser should only have parameters that are strictly necessary. Anything optional usually goes elsewhere, such as being a readwrite #property. There's some amount of leeway here, at your discretion - sometimes you'll include an optional parameter because it is actually used the vast majority of the time (and when it's not it has an easy default, like nil or 0).
The idea being that any object returned by an init method should be usable in some fashion. Requiring additional steps to configure it is almost always indicitive of a poor design.
Following this principle also encourages immutable instances (since in many cases you can specify all the necessary parameters upfront), which are advantageous for many reasons - simplicity, predictability, thread-safety, copy-by-retain etc, etc.
For a view controller specifically, typically you would have an initialiser which takes the view to be controlled, and leaves everything else as #properties. Your view controller should work, in some capacity, with just the view set; all other properties should have reasonable defaults.

Is it ok to call release on a property in Objective C?

I've been teaching myself Objective C recently, and have noticed the following pattern used a lot in tutorials and sample code (including samples from the Apple site).
UIView *myUiView = [[UIView alloc] init];
self.uiView = myUiView;
[myUiView release];
I was just wondering though, it seems a bit of a waste to create a new variable, just to set a property. I've also seen the following pattern used too, but from what I understand its considered bad form to use autorelease on an iOS device as the autorelease pool takes up quite a bit of overhead which might not be good on a mobile device
self.uiView = [[[UIView alloc] init] autorelease];
I've been toying with using the following pattern recently, which sets the property, and then calls release on the property (to decrease the reference counter on the property itself).
self.uiView = [[UIView alloc] init];
[self.uiView release];
I've managed to use it on a few ViewControllers with no ill effects, but is this valid code, or am I missing something which makes it a bad idea?
The property getter is a method, and it does not have to return an ivar, it may actually get its return value anywhere, so you could release that, but it could be an autoreleased value already. If that is the case, you're in trouble.
IOW, if a property getter would do something like (not usual, but possible and valid):
- (NSString *) helloString
{
return [[myStringIVar copy] autorelease];
}
and you do:
[self.helloString release];
then you failed in two ways:
You did not release the ivar you wanted to release
You release an autoreleased object
IMO, it is better to release the ivar directly:
[myStringIVar release];
If the implementation of the property getter is simply to return the reference to the underlying ivar, then it is perfectly equivalent and you simply decrease the retain count of the allocated object.
On the other hand, if you can't be sure what the getter does (what if it returns something else than the ivar, e.g. some calculated result etc.), it may be dangerous.
No. It's not valid.
It will probably work on most retain properties but not necessarily. It will probably break on copy properties and assign properties.
Properties are just a pair of methods, one of which sets an abstract entity and one which gets it. There is absolutely no guarantee in general that the getter will give you the exact same object that you just passed to the setter. For instance, if you pass a mutable string to an NSString copy property, you definitely won't get back the same object.
Use either of the first two patterns. The first one does not waste anything. It is likely the local variable will only ever exist in a register. The overhead of the second will only last as long as the next autorelease pool drain and is only a few bytes (bear in mind that the actual object will last as long as self in any case).
It's not valid, and even in the cases where it does work its a bit "ugly" the other two are just to fix the property's retain characteristic from making the retain count 2 after having an alloc already making the retain count 1.
I tend to do what you described in the first example or the following.
in my #interface
#property (nonatomic, retain) UIView *uiView;
in my #implementation
#synthesize uiView = _uiView;
then when I setup the property.
_uiView = [[UIView alloc] init];
Thinking in terms of the reference counter, nothing is wrong with calling release using the property value. However, there are a few things, which I (personally) would dislike:
The property syntax is really just syntactic sugar for method calls. So, what your code really looks like, is
[self setUiView: [[UIView alloc] init]];
[[self uiView] release];
Another thing here might be more due to me thinking in strange ways, but I like to think of the reference counts as actually being related to references. A local variable holding a pointer to my object is such a reference. Having it present in the code reminds me, that I have something to do in order to clean things up properly (or, if not, at least write a short comment, why I don't have to clean up).
Directly going through the property forces me to think in terms of reference counts instead, which I don't like.

Accessing an object outside scope in a controller class

In my controller class, I initialize two instances of a model class (whose header is properly imported into controller class) with an NSButton. The model is really simple, just 4 members and one method - attack(). Making a silly text game!
- (IBAction)startGame:(id)sender {
Combatant *hero = [[Combatant alloc] init];
Combatant *enemy = [[Combatant alloc] init];
[console insertText:#"You have created a hero! An enemy approaches...\n"];
}
So now I have these two objects sitting there. Or do I? Because this other button, the one that's supposed to make them fight, has no idea what hero and enemy are, or that they have a class method that makes em' fight!
- (IBAction)attack:(id)sender{
[hero attack:enemy]; //Use of undeclared identifier, blah blah.
[console insertText:#"You attack the enemy! Woah!\n"];}
I get that if I initialized those objects in the attack method, then I could use them, so I gather this is something to do with scope. But I don't like the idea of sending model objects to controller methods, that seems silly.
Let me apologize: yes, this is a stupid, high-level question about the structure of Cocoa. Sorry. But I figure one of you will know exactly what I am not doing and tell me to do it!
In short, what is the Cocoa way of doing things in this situation? Thanks in advance.
-Alec
When you declare a variable in a method, it is a local variable, which means it only exists in that method. The same goes for variables you declare in functions.
If you want the variable to exist in all instance methods in the class, you need to make it an instance variable, which you do by declaring it in that { … } section in the class's #interface.
Note that any objects you store in instance variables, the instance should own. This means three things:
You'll need to either retain the object (and thereby own it) or make a copy (which you will then own) before assigning it to the instance variable.
Since you own it, you'll need to release it in the instance's dealloc method.
If you decide to replace it with a different object, you'll need to release the former object (since you still own it) and retain or copy the new object (in order to own it).
See the Objective-C Programming Language and the Memory Management Programming Guide for more information.