I\'m just starting out (reading up a lot for the past couple of days). Here\'s some questions that I have stacked up, hopefully someone can answer them.
1.
self
pointer is something that the system should do, and not the programmer.Also, many people prefer to keep the main line of program flow as un-indented as possible. In which case the initialisation code could be re-written as:
- (id)init {
if (![super init]) {
return nil; // There is a problem so bail early.
}
// Initialisation code here.
return self
}
Will Shipley explains this much better than I do.
In Objective-C, it's possible to return an instance other than self from -init
. Classes do this, for example, to enforce a singleton instance, or in the case of class clusters. NSNumber
, for example, returns a subclass depending on the type of value passed to its initializer. So when you call [[NSNumber alloc] initWithLong:long_value]
, NSNumber
's -initWithLong:
initializer is called after NSNumber
's +alloc
, but a subclass of NSNumber
may be returned to the oringial caller. Thus the pattern
self = [super init];
which reassigns self
to the value of [super init]
so that self
points to the actual instance that [super init]
returned. If +alloc
or the super's init
method fails, the result of [super init]
may be nil
. To avoid, side effects in the case of a failed initialization, the pattern then becomes
- (id) init { if(self = [super init]) { // do initialization of instance variables etc. } return self; }
Note that you must return self
(or nil
or an other instance) from the init
method. You should assign self to [super init]
and you may check for nil
before doing more work.
You may have to release the return value of a staic method. You should read the Cocoa memory management guide. The rule is generally quite simple: If the method you call has "new", "alloc", or "copy" in its signature, the result belongs to the caller and the caller must call -release
on that instance or there will be a memory leak. Of course you should call -retain
on anything else (i.e. not from an "alloc","new" or "copy" method) you want to keep a reference to and then call -release
or -autorelease
when you are done with that instance.
str = @"Hi there!"
, assuming str
was declared as NSString *str;
assigns the address of the string constant @"Hi there!" to the value of the
strvariable. You do not need to retain or release string constants.
str = [[NSString alloc] initWithString:@"Hi there!"];allocates a new string instance. The value of
strwill be the address of this instance. Each call of
str = [[NSString alloc] initWithString:@"Hi there!"];again will allocate a new instance. So after
str2 = [[NSString alloc] initWithString:@"Hi there!"];,
str != str2, while after
str2 = @"Hi There!", str==str2
. See this answer as well.
-autorelease
adds the receiver to the current NSAutoreleasPool
. When the pool is drained (usually at the end of the current run loop iteration, or when the pool is manually drained), the pool calls -release
on all instances in the pool. If this -release
drops the retain count to 0, the object is deallocated (and -dealloc
called) just as with any other -release
. Using an autorelease pool is generally frowned upon on the iPhone because it may cause you to accumulate many unused instances in the pool before it is drained at the end of the run loop iteration. If you can use -release
instead of -autorelease
, you generally should. Again, see the Cocoa memory management guide for more info.
If self is nil after the super initialisation then you're probably out of memory. Your only reasonable course of action is to return nil and hope things get handled gracefully further up the stack.
Static methods aren't allowed allocate on the heap, therefore there's nothing to free.
In the first instance, the string is compiled into the data segment of your app and cannot be freed. In the second instance, you are allocating memory from the heap and copying your static string (from the data segment) into it.
It's simple garbage collection. As to why to use it, the simple answer is don't. It's not recommended to use autorelease on the iPhone due to limited resources.
1: This check is to ensure that the super constructor returned a new object.
2: Static methods don't refer to an instance
3:
str = @"Hi there!"
This assigns the address of the constant string "Hi there!" to the pointer str
str = [[NSString alloc] initWithString:@"Hi there!"];
This allocates a string and copies "Hi There!" to it. This means that a) str is modifiable and b) needs to be deallocated when you are done with it.
calling
self = [super init];
May return nil if the superclass cannot initialize itself for some reason or other, including memory being unavailable, or certain prerequisites have not been met. If that is the case, you don't want to be trying to set variables of self, or set self as a delegate, or add self to an array, if self is nil.
The autorelease pool is something created upon every event the iPhone sends your application. It is created before any code runs, and released after all your code is done, for each event. Any objects that you call autorelease
on will be put into the current autorelease pool. Any objects in the autorelease pool will be released as many times as they were added, after your code completes. In this way, you don't have to worry about who's responsible for releasing an object created by one method and returned to another method.
You can create your own autorelease pools as necessary.
str = [[NSString alloc] initWithString:@"Hi there!"];
This line creates a string that is not in an autorelease pool, so you have to release it manually. Simply writing
@"Hi there!";
returns a string that you don't have to worry about releasing. Extending your previous example:
str = [[[NSString alloc] initWithString:@"Hi there!"] autorelease];
would be another method of creating a string you don't need to worry about releasing.
One difference between garbage collection and autorelease pools is that garbage collection works with circular references. Using autorelease pools, you don't want to have two objects that retain each other and hope that once nothing else refers to them, they will go out of existence; they won't.