I am new to Objective C. I have trouble with understanding the init() method. I have read these two lines on Apple website:
The init() method defined in the NSObject class does no initialization; it simply returns self. (https://developer.apple.com/reference/objectivec/nsobject/1418641-init)
You must use an init... method to complete the initialization process. (https://developer.apple.com/reference/objectivec/nsobject/1571958-alloc)
Do I need to call init() to initialize objects if "it does no initialization"? Why?
When an instance object is created with +alloc, it gets a fully set-up infrastructure and all ivars are set to 0, NULL, nil, 0.0 (or whatever ist the zero value for the ivar's type).
If this is enough for the class, there is no need to overwrite -init and it can simply use NSObjects init. (-init of NSObject simply does nothing.) This is the implementor's side. This is what you refer to at 1).
The user of the class (that code, that created the instance), has to send init to the newly created instance to give it the opportunity to initialize itself. This is what you refer to at 2).
As a user of the class, you simply cannot know and should not know, whether the class requires some code in its initialization process. So send the message, even if it might be useless.
From Apple Developer on Object Initialization :
If an object does not implement an initializer, Cocoa invokes the
initializer of the nearest ancestor instead.
Yes, you need to call some form of init to create your object on the heap. The init returns a point to the memory location. No, you don't need to write an init for your custom object unless the default set-everything-to-zero initialization is insufficient.
Related
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.
I have this from either the Apple documentation or the swift book
When an instance gets deinitialized, you still have access to the
properties inside the instance and can manipulate them as needed
before the instance totally goes away.
I'm confused, do they mean when we for example do some mathematical action using the instances property in the deinit() method? or lets say when we print a property of type string that was part of a specific instance, also from the deinit() method?
If so, then is the deinit() method the only way to manipulate a property when it is being deinitialized?
if you have a swift class with a a var you know you have to clean up after because ARC can't free it (e.g. C memory), you can still do that in deinit. The pointers stored in the properties are still valid!
it isn't useful for much more though (ok end observing with the notification center or kvo) BECAUSE there is no guarantee WHEN deist is called. ONLY that it is called before deallocation [whenever that is]
deinit is called right before deallocation (when the retainCount reaches 0), so all your properties are still valid and you can print your string. You don't need to set properties to nil explicitly in deinit as that happens automatically.
This being said, most classes don't even need deinit implemented
Most of the time I used deinit to remove observer that the instance is registered to, post any notifications if needed, and things like that.
As far as I know, the deinit method gets called just before the instance gets deinitialized, to give you a final opportuninty to do whatever you need to do (cleanup, close a file, terminate a network connection, etc).
What the documentation says is that, at the time deinit is called your object has not been deinitialized yet (but will be very soon), so you still can (for the last time) access its properties.
// 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.
I'm building an iOS app in Swift and drawing on the Lister sample project Apple provides.
Lister uses two model objects: List and ListItem. I found that both of them do not call super.init() in their initializers even though they subclass NSObject.
However, in the Objective-C version of Lister, both model objects (AAPLList and AAPLListItem) do call [super init].
The Swift Programming Language clearly states that “designated initializers must call a designated initializer from their immediate superclass.” (Rule 1 of Initializer Chaining in Initialization)
What's going on here? Why is this an exception and if you shouldn't always call super.init() in a subclass, what rules do apply?
Even though I can't find a place in the documentation where this is described, what happens is that the default superclass initialiser is called at the end of the subclass initialiser if that is the only initialiser of the superclass, and it wasn't called explicitly.
NSObject only has the default initialiser (init()); you can see that the superclass initialiser is called at the end of the subclass initialiser by attempting to reference self (eg. println(self)) in a constructor that does not call super.init(): You are not allowed to do it because the class is not fully initialised at that point.
If you want to use self somewhere in the constructor, the object needs to be fully constructed at that point, so you need to call super.init() manually before then.
What is the purpose of the initializer pattern other then in order to assure that the object is properly initialized by its superclass before the init method performs its initialisation.
Why is this necessary?
and
when we have a class which has more than one initialization method, why others shoud call the dedicated initialiser instead of superclass initialiser?
I'm coming from java background so don't fully understand this - the closest i could match in java was singleton pattern but the part others calling dedicated initialiser didn't make sense to me as in java you have a choice rather then you "should".
can any one elaborate....thx
The initializer pattern is necessary, because the super class whose initializer you are calling, can return any kind of object, not necessarily the instance of that class. That's how, for example, NSString works, it's actually a cluster of classes implementing different kinds of strings optimized for different usage patterns. So calling self = [super init] for NSString descendant makes self, for example, an NSCFString instance.
There's a pattern called Designated Initializer in Objective C. If the class has many initializer, one of them is chosen as designated, and all the other should be implemented by calling it, not the super. This is important for correctly overriding initializers in child classes, you should initialize only the designated one, and it will be called under all circumstances (assuming your code is well-written and takes advantage of designated initializers, of course :)