As far as I know you should always use accessors to access or modify a property, except in two scenarios:
init
dealloc
Don’t Use Accessor Methods in Initializer Methods and dealloc The only
places you shouldn’t use accessor methods to set an instance variable
are in initializer methods and dealloc. To initialize a counter object
with a number object representing zero, you might implement an init.
This exceptions are because calling accessors when the view is not completely initialised might raise issues when overriding the setters/getters (https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html)
So, according to this the use of accessors on viewDidLoad should be perfectly fine, and even recommended, however in most of the codes available on internet developers use _ivars on viewDidLoad and I wonder why. Is there a reason for using property _ivars instead of accessors in viewDidLoad?
One of the most valuable post about using accessors in init/dealloc method
https://www.mikeash.com/pyblog/friday-qa-2009-11-27-using-accessors-in-init-and-dealloc.html
you should always use accessors to access or modify a property
Where did you read this?
When you want to access a property, you can use _ivar (or self->_ivar) to access the instance variable directly without passing by the getter, it would be faster that resolving and executing the getter.
However, if you use a custom getter then it won't be executed.
Often property accessors are overridden to update the view, which is inefficient if the view is not visible yet. So it is possible the code you found that ivar directly is using that to prevent that. However, much better is to use the property but check if the view is visible and only update if necessary. The same method can be called from viewWillAppear.
Related
// apply borders to the buttons
-(void)viewDidLoad
{
[super viewDidLoad];
[self.hostGameButton MH_applySnapStyle];
[self.joinGameButton MH_applySnapStyle];
[self.singlePlayerGameButton MH_applySnapStyle];
}
I am confused about this piece of code. If self is just referring to the instance of that object and when we use #property it creates an instance called _hostGameButton ... etc; why can't we just use this code instead?
[_hostGameButton MH_applySnapStyle];
You can, it's just not considered good practice or style. It breaks the encapsulation created by using properties, as well as the (usually desirable) KVO notifications the accessors generate. Modern Objective-C practice is to use properties for everything and only access the synthesized ivar in the init, dealloc (if necessary), and lazy accessor methods, if necessary.
Instances are the heart of the action in an Objective-C program. Most of the methods you’ll define when creating your own classes will be instance methods; most of the messages you’ll send in your code will call instance methods.
So when you create instance of something(like uibutton,uitext field) as property you can access
it anywhere in your.m file by using self. But if you create instance of it in a class you can access it only in that class but no where outside.
As per Apple Documentation, if you’re accessing an object’s properties from within its own implementation, in this case you should use self.
Since Objective-C 2.0 we have properties, a nice syntax for getting and setting values for instance variables. Since Clang 3.1 all properties which are not dynamic, not readonly with an explicit getter or don't have a custom getter and setter are automatically synthesized to ivars. And since ARC we have weak/strong annotations for properties which are used by ARC to define the memory management logic of automatically synthesized properties.
The properties still can be synthesized manually e.g. for a readonly property backed by an ivar and returning a default value, for instance.
Sometimes, properties are also useful if they are not synthesized at all. I have found a few use cases when I use this sort of behavior:
A custom getter and setter which use a custom ivar for storing the actual value and which perform some additional actions.
A dynamic property, e.g. in subclasses of NSManagedObject.
A readonly property which simply passes through a property of an object stored in another property (e.g. a private one).
The Question: Does it makes sense to annotate these non-synthesized properties with weak/strong according to their actual usage or not? What is the best practice?
(https://twitter.com/kubanekl/status/427142577310408704)
I would say the answer is yes, even if only for documentation sake.
Even if you do not use any of the compiler and framework related default implementations, and implement everything by yourself, someone attempting to use these properties will be in much better position of understanding the API if he is able to get a hint on how the memory management would behave. A person does not really have to know how a setter or a getter is implemented internally, but he would might have to know, for example, if after calling a setter, the value was copied or retained or just assigned, and implement his side of things accordingly.
Yes, it does.
The property definition is a contract specification. Just because the compiler isn't fulfilling the contract doesn't mean you shouldn't respect it when manually implementing the accessor methods.
I have a understanding problem with one aspect of KVC and accessor method.
When I access my getter/setter methods with self.variable/self.setVariable the method observeValueForKeyPath:ofObject:change:context: gets executed
But if I understand apples documentation correctly from here
[...] and then uses setValue:forKey: to set the new value. This
maintains encapsulation of the model and ensures that any additional
actions that should occur as a result of setting the value will
actually occur. This is considered better practice than calling an
accessor method or setting an instance variable directly.
it should not get executed.
Is there something else that gets executed when I use setValue:forKey: which is not getting executed when I use the getter/setter methods?
What is getting executed when I use setValue:forKey: which isn't executed when I use the accessor methods?
Code example here
The Apple Programming with Objective-C document states that:
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.
But I don't know what side effects will be in a setter method, please give me a example to explain why I have to access the instance variable directly from within an initialization method
The answer is simple - it is code smell. Dot notation like self.foobar = something in Objective-C is just a syntactic sugar for messaging.
Sending messages to self is normally fine. But there are two cases you need to avoid them:
1. When the object is being created, and
2. When the object is being destroyed.
At these two times, the object is in a strange in-between state. It lacks integrity. Calling methods during these times is a code smell because every method should maintain invariants as it operates on the object.
If a setter method is overridden by a subclass, you have no guarantee that your instance variable will contain the correct data. If you want to maintain data integrity within your objects during a crucial phase such as initialization, you should do as Apple recommends.
In addition to #JacobRelkin point, side effects can include Key-Value Observing. Other objects can observe changes even during -init* and -dealloc. I've had a KVO -dealloc bug in the past.
It truly is a best practice to setup and tear down the ivars directly.
Is there a difference between using the underscore and using the self keyword in Objective-C when calling an #property?
Property declaration:
#property (weak, nonatomic) NSString *myString;
Calling #synthesize on the property:
#synthesize myString = _myString;
Is there a difference if I want to use it in my code? When? In the getter/setter?
self.myString = #"test";
_myString = #"test";
self.myString = #"test"; is exactly equivalent to writing [self setMyString:#"test"];. Both of these are calling a method.
You could have written that method yourself. It might look something like this:
- (void)setMyString:(NSString*)newString
{
_myString = newString;
}
Because you used #synthesize, you don't have to actually bother writing that method, you can just allow the compiler to write it for you.
So, from looking at that method, it looks like calling it will do the exact same thing as just assigning a value to the instance variable, right? Well, it's not so simple.
Firstly, you could write your own setter method. If you do so, your method would get called, and it could do all sorts of additional things as well as setting the variable. In that case, using self.myString = would call your method, but doing _myString = would not, and thus different functionality would be used.
Secondly, if you ever use Key Value Observing, the compiler does some very clever tricks. Behind the scenes, it subclasses your class, and overrides your setter method (whether it's one you wrote yourself or one generated by synthesize), in order to make the calls to willChangeValueForKey: that are needed for Key Value Observing to work. You don't need to know how this works (although it's quite interesting if you want some bedtime reading!), but you do need to know that if you want Key Value Observing to work automatically, you have to use setter methods.
Thirdly, calling the setter method even if you're relying on synthesize to write one gives you flexibility for the future. You might want to do something extra whenever a value is changed, and at the point you discover you want to do that, you can manually write a setter method — if you're in the habit of always using self.myString =, then you won't need to change the rest of your code to start calling the new method!
Fourthly, the same applies to subclasses. If someone else was to subclass your code, if you use the setters then they could override them to adjust the functionality.
Any time you access the instance variable directly, you're explicitly not providing a way for extra functionality to be hooked in at that point. Since you or someone else might want to hook in such functionality in the future, it pays to use the setters all the time, unless there's a good reason not to.
You are correct - the first version (self.myString) calls the synthesized getter/setter and the second version access the private member variable directly.
It looks like you are using ARC, so in that case it doesn't make that much of a difference. However, if you aren't using ARC, it can make a difference as assigning to the private member directly won't trigger the automatic retain/release or copy/release logic that is generated for you by using synthesize.
The _ (underscore) is simply a convention, as explained in this question.
When you don't prefix a property access with self., you are accessing the underlying variable directly, as in a c struct. In general, you should only ever do this in your init methods and in custom property accessors. This allows stuff like computed properties and KVC to work as intended.
There is a tip not mentionend, the access using underscore is faster and the access using self is safer (KVC). Maybe this can summarise when you have to use each one.