Returning an object from a method
It's quite common for a method to return an object, but there are several things you should consider.
First of all, are you returning an already existing object or are you creating one?
If you are creating one, do you need to keep it?
If the object was already existing, you can simply just return it in most cases.
If it is created in the method, there are two possibilities.
The created object won't be used anymore after that
You want to keep the created object for later use.
In the second case, we are probably in a case of lazy allocation. It's a name given for the initialization of a class attribute outside an init method.
- (id)myMethod {
if (!m_myAttribute)
{ /* If the object wasn't allocated yet */
@synchronized(self)
{ /* To protect this part from multiple access */
if (!m_myAttribute)
{ /* If the object is still not allocated (second part of the security against multiple access) */
m_myAttribute = [[MyClass alloc] init];
}
}
}
return m_myAttribute;
}
The first time this method is called, the object will be allocated and initialized before being returned. The second time the already allocated object will only be returned. So, as a matter of fact, we mustn't autorelease this object because it will be reused.
Delegation
As I am writing from my phone, today's article will be short.
When creating your cocoa's application, you will often be asked to set a delegate object. This is not specific to objective-c development.
I will take a simple example : a table. There exists two ways two create cells in a table. The first one is active, we tell the table to add a cell, and we do so for each cell. The second one is passive. When the table want to be draw or updated, he ask our code what it should do.
How many rows should I have? What cell should I display there? What should I do when my cell is selected?
That is delegation. The answers are given by an instance of a class implementing an interface. This object is the delegate.
As a matter of fact, in iOS development, a UITableView use a double delegation. The delegate defines the behavior while the datasource defines the content.
The reference-counted memory management system
Cocoa use a counter, the retainCount to know when an object must be deallocated.
When an object is initialized, its retainCount value is set to one, meaning "I am used at one place".
During it's life, this object may encounter several call to retain or release.
When retain is called, the retainCount value is incremented, meaning "I am used at one more place". Inversely, when release is called, the retainCount value is decremented. When the counter value reaches zero, the object is deallocated.
The autorelease method is a variant to the simple release one. When an object receive this message, it adds itself to the nearest autoreleasepool. When this pool is released or train, all objects that were put in it receive a release message.
You can create your own autoreleasepool, sometimes you must do it. There exist at least one pool in your program, located in the event loop.
Objective-C Class Initializer
This post is the first in a series of posts about Objective-c / Cocoa programming tips.
As you should already known, a basic initializer for an objective-c class looks like this:
- (id)init {
if (self = [super init]) {
/* Put your code here */
}
return self;
}
But what does it mean?
Firstly, the minus sign tell us it is an instance method. It can only be called on an already allocated object.
Secondly, your initializer returns an id object. An id object is more flexible to use than a pointer, it can refer to any kind of object. It also allows to call method that aren't on the interface declaration, without getting a warning from the compiler.
Thirdly, we put the result of the call to the super initializer in our self pointer. This pointer represents the object we are currently initializing. As a matter of fact, in most cases we don't need to to change the self value. It is only a security in case the super initializer would return something else than the object to be initialized. I don't know any class where it can happen, but it's better to be careful.
Finally, if the call to the super initializer fail, that is to say if it returns a nil pointer value, the initialization code isn't executed and nil is returned by this method.