Why is -init an instance method and +initialize a class method? [duplicate] - cocoa-touch

This question already has an answer here:
Why is init not a class method?
(1 answer)
Closed 8 years ago.
In Cocoa, for NSObjects, shouldn't both init and initialize be class methods?

+initialize can be overridden (it's optional) to perform class-wide initialization.
-init performs initialization of a single instance of a class, though it's often refined by adding arguments in classes derived from NSObject (ex: UIView's initWithFrame: method).
Since -init initializes a single instance (in particular, it has access to the instance's variables), it can't be a class method.

From the docs:
The runtime sends initialize to each class in a program just before the class, or any class that inherits from it, is sent its first message from within the program.
This means that the first time you send a message to the class, whether it be alloc or some defined class method, initialize is called first, once, for the entire run of the application. As opposed to load, it is possible to include a class in a project and never hit initialize.
init, on the other hand, is
Implemented by subclasses to initialize a new object (the receiver) immediately after memory for it has been allocated.
Meaning, init is sheerly used for initializing class instances.
Edit --
Following the edited question, alloc creates the instance while init initializes it, which is why alloc is a class method and init is an instance method.

Related

Why does registering a subclass with its superclass in +initialize present a chicken and egg issue? (objc)

Just reading an excerpt from this website.
Because +initialize runs lazily, it's obviously not a good place to
put code to register a class that otherwise wouldn't get used. For
example, NSValueTransformer or NSURLProtocol subclasses can't use
+initialize to register themselves with their superclasses, because you set up a chicken-and-egg situation.
I understand that +initialize is run once per class when the first message is sent to that class. Also, if any of the subclasses do not implement their own +initialize, the +initialize method will be run again in the superclass.
I am just not 100% on why registering a subclass with its superclass in its own +initialize method would present a chicken and egg problem.
Is it because the superclass may have never had its +initialize invoked, and you are trying to register your subclass with its superclass in a method that depends on the superclass calling its +initialize first?
Just a little bit of further clarification would go a long way for me, thank you.
Take the example of NSURLProtocol. The way it's used is that registered subclasses are asked, in turn, if they can handle a request. The first to answer yes gets an instance created and the request is handed off.
The initialize method is only called if a message is sent to the class. Since only registered subclasses are asked to handle a request, you can't register in initialize because it won't ever be invoked.
Two extracts from the documentation on the initialize method:
The runtime sends initialize to each class in a program just before the class, or any class that inherits from it, is sent its first message from within the program. The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses.
...
Because initialize is called in a thread-safe manner and the order of initialize being called on different classes is not guaranteed, it’s important to do the minimum amount of work necessary in initialize methods. Specifically, any code that takes locks that might be required by other classes in their initialize methods is liable to lead to deadlocks. Therefore you should not rely on initialize for complex initialization, and should instead limit it to straightforward, class local initialization.
The initialize message is sent to a class the first time the runtime encounters it, for example the first time you need to allocate that class or the first time you access its sharedInstance method (in case of a singleton), and it acquires some locks in order to guarantee the thread safety. If you make references to subclasses from within this method, you can get into a deadlock situation, as both the base class and the subclass will lock onto the same thing.
For example, let's consider the scenario of a superclass MyClass and one of it's children MySubclass:
#interface MyClass
#end
#interface MySubclass: MyClass
#end
#implementation MyClass
+ (void)initialize {
[MySubclass doSomething];
}
When the runtime encounters the first usage of MyClass, it acquires a lock, and calls the class method initialize. Now, when executing the method it realises that this is also the first time it encounters MySubclass, and must also intialize it before the class can do some actual work. And what does this trigger? Yes, you've guessed, another call to +[MyClass initialize].
This how we end up in the chicken-egg situation, or to put it more technical - the deadlock, or the recursion. MyClass calls on MySubclass, this means that MySubclass needs to be initialized before MyClass is used. However MySubclass is a child of MyClass, so MyClass should be initialized first. So, which one the two should be first initialized?

Why is init not a class method?

Why is the init method not a class method? I mean init's method body starts with an -.
Methods starting with - are instance methods as far as I know, but obviously we want to create an instance.
init is not for creating an instance; that's alloc's job (and alloc is a class method).
init is for setting up the created instance. It needs access to the new instance's ivars, and must be an instance method.

What's the difference of instance method and class method in Objective-C? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Objective-C: Class vs Instance Methods?
Objective-C - difference between class method and static method?
In ObjC, A single dash before a method name means it's a instance method. A plus before a method name means it's a class method. but what is the difference in programming?
The difference between a class method and an instance method is that an
instance method requires an instance of the class on which it will
(generally) operate. The message to invoke an instance method must be
sent to an instance of a class.
Probably the most common single use of class methods is object
factories; messages that you send to a class to create an instance
configured according to the parameters you've sent in. For example in
Cocoa the NSString class has several class methods named
stringWithSomethingOrOther: that will create a new NSString object and
hand it back to you.
On the other hand, NSString also has many instance methods -
operations which really have no meaning without an actual instance to
work with. A commonly-used one might be the length method, which tells
you how many characters are in the specific NSString instance to which
the message is sent.
Also see this.
What is the difference between class and instance methods?
An instance method is invoked on objects. A class method is invoked on class.
For example the line:
SomeClass *object = [[SomeClass alloc] init];
Here you can see that the "alloc" works on "SomeClass" and not on "object".
Whereas:
[object callMyFunction]; will act on "object" and not "class". This is an instance method.
The main difference with those two is the former one ie with single dash before it is only called by the instance of that class where it is declared ie one have to create one instance of that class means one object for that class and using . one can call the instance method
In class method, the later one can be called directly using the class name. To call class methods one dosen't need any object.
Please refer this link from apple developers documents

Ok to skip init method in inherited class?

Consider the following text in http://developer.apple.com/library/ios/#documentation/general/conceptual/CocoaEncyclopedia/Initialization/Initialization.html.
Inherited initializers are a concern when you create a subclass. Sometimes a superclass init... method sufficiently initializes instances of your class. But because it is more likely it won’t, you should override the superclass’s initializer. If you don’t, the superclass’s implementation is invoked, and because the superclass knows nothing about your class, your instances may not be correctly initialized.
On the same page I find this text:
Every object that declares instance variables should implement an initializing method—unless the default set-everything-to-zero initialization is sufficient.
My question is:
If I skip the init method in class B, where class B inherits from A, can I trust that B's non-inherited member variables are set to zero?
My question is: If I skip the init method in class B, where class B
inherits from A, can I trust that B's non-inherited member variables
are set to zero?
Objective-C will set all ivars of any new object to zero:
The alloc method dynamically allocates memory for the new object’s
instance variables and initializes them all to 0—all, that is, except
the isa variable that connects the new instance to its class. For an
object to be useful, it generally needs to be more completely
initialized. That’s the function of an init method.
So it's okay to skip implementing an initialization method for your class if you don't have any ivars/properties that need to be initialized. You must, of course, still initialize new objects by calling -init or some other initialization method so that the superclass has an opportunity to initialize itself.
Yes, Class B's non-inherited member variables will be zero. Inherited variables will have whatever value is set in Class A's init method (or zero if not set).

When do we create memory for ivars in Singleton example by Apple?

I have seen the Apple's example of Singleton and couple of other examples.
People say that it is too strict!
But the point is ..even if it is too strict, I want to understand it.
I dont understand that when we call allocWithZone on super, What happens ?
Memory will be created according to super's instance size.
What if our Singleton has ivars ?
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32
I also dont understand that, Why does allocWithZone return the object with a retain call when retain itself is returning the object as it is.
Whenever a method is called in Obj-C it is passed an object reference via the hidden parameter self. For an instance method self refers to the object the method was invoked on, for a class method self refers to the the class object (of type Class) the method was invoked on. Calls to super implicitly pass on self.
Therefore in Apple's example code the call [super allocWithZone:NULL] calls the super implementation of allocWithZone passing the current value of self, which is MyGizmoClass's class object as it is a static method. The implementation of allocWithZone can determine the required memory size from the passed Class object – the details of how are private.
As you've correctly spotted, the call to retain in allocWithZone is pointless but harmless.