Why is alloc needed in Objective-C object initialization? - objective-c

I have been going over some tutorials in Objective-C and I am confused when it comes to the command alloc() and how it is used to initialize an object.
The tutorial says to do the following and I am having trouble figuring out why it is necessary.
Change
NSDate *now = [NSDate date];
to
NSDate *now = [[NSDate alloc] init];
Why is this change necessary since the first line works just fine? I guess I am looking for how the two lines differ. Thanks!

There's a simple difference and a deeper one.
The simple answer is that the first method includes an +alloc/-init pair internally—the documentation tells us that it returns a new date object initialized to the current time. Generally, somewhere, somebody has to call +alloc and an -init method of some sort. Sometimes that's you, sometimes a convenience method has been included for you.
The deeper answer about the difference is that +alloc/-init returns an object that is owned by the caller, who is then responsible for calling -release at some point, while convenience constructors that don't start with the words "alloc" or "new" return autoreleased objects that you don't have to release. However, if you are using ARC, this is mostly academic, as the compiler tracks that detail for you.

Break it down:
NSDate is a class. So NSDate alloc is a call to the class method alloc. That's actually inherited from NSObject and acts to create sufficient storage for a new instance of NSDate, then return it for use as an instance.
(instance) init is a call to the instance method init. Prior to calling init the instance you've received is not guaranteed to be in a valid state. Calling init or the relevant initialiser gives the instance the chance to establish itself.
NSDate also choses to supply the class method date. That does the same thing as [[[NSDate alloc] init] autorelease] and is provided as a mere shorthand.
As other posters have commented, there is a semantic difference here — alloc returns an owning reference. So it's the caller's responsibility to release the object later. date returns a non-owning reference. So the caller has no responsibilities. However the modern ARC compiler will deal with releasing things for you. So there's a difference but not one that has any real effect on you.
If your tutorial insists that date is more proper then either it was written before the ARC compiler or was written by someone that prefers to use the old conventions; using date would traditionally communicate that the thing you were creating was for transient use so there is arguably some extra value in the one way versus the other for an experienced developer.

With ARC it doesn't matter as you no longer have to release objects you alloc init.
Without ARC the difference in important:
[NSDate date]
returns an autoreleased object using a class method on NSDate.
[[NSDate alloc] init]
returns a non autoreleased object instance, with a retain count of one.
As in non- ARC, you need to take memory management in your own hands, So, alloc init is better option. So, that you can release it, once not required.
One further point to note, is that autoreleased objects are released when the autorelease pool is.
When you alloc init you know that your object will stay around until you release it (or you leak it because it goes out of scope).

The change is not necessary at all. It doesn't matter if you create object using alloc+init or using convenience methods. Think about them as legacy and convenience methods.

Related

Cocoa example - Why there is NO need to retain or release messages

I'm new to Objective-C and cocoa. In the guide provided by Apple for Cocoa, there is a confusing example in memory management:
Suppose you want to implement a method to reset the counter. You have a couple of choices. The first implementation creates the NSNumber instance with alloc, so you balance that with a release.
- (void)reset {
NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
[self setCount:zero];
[zero release];
}
The second uses a convenience constructor to create a new NSNumber object. There is therefore no need for retain or release messages
- (void)reset {
NSNumber *zero = [NSNumber numberWithInteger:0];
[self setCount:zero];
}
I am not sure why the object is created with 'new' instead of 'alloc & init' does not need to be retained/released. My understanding is that both are doing the same thing, except that with 'alloc & init' we can use custom checks and initialisation.
Many thanks.
The second example returns an auto released object. The code for the convenience constructor probably looks like this, at least when it comes to replicate the functionality.
+ (NSNumber *)numberWithInteger:(NSInteger)integer
{
NSNumber *number = [[NSNumber alloc] initWithInteger:integer];
return [number autorelease];
}
Autorelease is a way to defer sending a release method to an object while not delegating ownership of the object to the caller of the constructor. This is an important concept, because the naming conventions require you to not return ownership of an object unless your method starts with copy new alloc or retain. However, since you can't return an owned object, you would have to call release on it in your convenience constructor, which would then lead to you returning a deallocated object. So, autorelease allows you to return an un-owned object to the caller which will receive an actual release method later (when the current autorelease pool gets drained).
Autorelease methods are collected in so called autorelease pools, which are thread local quasi linked lists (they are not implemented as linked lists, but they do work like they were) and that just collect autoreleased objects. Objects can be added to them multiple times by calling, once for each autorelease method they receive. When the pools is drained or destroyed, all objects it contains will receive a release message. By default, the system will provide you with an auto release pool, at least on the main thread, but you can create your own ones using this code (which is also used in every main method, if you take a look):
#autoreleaspool
{
[foo autorelease]; // foo will receive a `release` method at the closing brace
}
By convention, all methods who's name start with "alloc" or "copy" or "new" increase the retain count by 1.
All other methods do not change the retain count. Since "numberWithInteger" doesn't start with "alloc" or "copy" or "new" it returns an object with a retain count of 0. But instead of setting it to 0 immediately (which would never work), it sets the retain count to 1 and then schedules it to be dropped down to 0 at some point in the future (usually when the event loop is idle, but you can manually make it happen sooner), using an "autorelease pool".
The only exception to the alloc/copy/new naming convention is, of course, the actual "retain" and "release" and "autorelease" methods, which increase/decrease the retain count or schedule it to be decreased later.
It is not a language feature, it's just a coding practice. Every method starting with "alloc" and "copy" and "new" sets retain to 1, everything else sets it to 1 but schedules it to be dropped to 0 later.
Of course, if you are using ARC, and you should absolutely be using ARC, then you don't have to worry about any of this because the compiler will find the last line of code that uses the object, and will insert a line of code after it to free up the memory. This leads to faster code, because the autorelease mechanism is a bit slow and sometimes uses too much RAM.
When ARC is enabled, none of those rules apply. The compiler ignores all your memory management code (or tells you to delete it), and writes it's own code. It's not actual garbage collection, it's just manual memory management that is generated by Xcode instead of written by hand.
Objects that are created with +alloc -init are returned with a retain count of +1, meaning that you have to call -release when you are done with this object. This is the same with +new , which is just a simple combination of [[ alloc] init], eg.
NSDate *date = [NSDate new]; // I will have to send -release at some point
As a convention, methods that contains init, new, create and copy will transfer ownership to you, meaning that you need to send -release at some point. Other methods will not transfer ownership, meaning that the object is autoreleased, ie. it has a short lifetime and is scheduled to be dealloced in the future. If you want this object to stick around, you will need to explicitly take ownership by sending -retain.
NSDate *date = [NSDate date]; // I won't have to send -release
// But this object will be dealloced soon
// so if I want it to stick around, I will need to retain it
This convention is not enforced by the language.
It is also useful to remember that this convention expands beyond the Objective-C part of the SDK, it is also the case in CoreGraphics and all C frameworks provided by Apple, and most third-party frameworks make use of this convention.
CGContextRef context = UIGraphicsGetCurrentContext(); // I won't have to release this context
CGImageRef result = CGBitmapContextCreateImage(context); // I will have to release this image
/* ... */
CGRelease(result);
As for your example : -numberWithInteger: does not contain either init, new, create or copy. So you don't need to -release it when done.

difference between – initWithRequest:delegate: and +connectionWithRequest:delegate

I want to know the difference between –initWithRequest:delegate: and +connectionWithRequest:delegate: of NSURLConnection?
Just the first one is no-aotorelease object and second is autorelease?
I want to know which one should I use in my ios code?
You've already pointed out the difference
For iOS codes, it's best to use use Alloc/init rather than convenience auto release functions because they stay around after you are done using them and there is no way for you to release them
Use autorelease when it's not possible to know when to call release (such as when you are returning a object that is not being retained elsewhere) The closest autorelease pool will free the memory the next time the pool is drained.
If you do use alloc/init, remember to call release, otherwise it will linger on in the memory
All methods in Objective-C that starts with init require to be called only after alloc method. Also init-method returns non-autoreleased object.
All methods that starts from name similar to class name, for example, [NSString string], [NSArray array] and others returns autoreleased objects and don't require precalled alloc method.
Returning to you question: you can use any of that approaches: alloc + initWithRequest:delegate: or connectionWithRequest:delegate: but be sure to release object in first case.
I think you pointed out the only difference.
I use the +connectionWithRequest:delegate: method
I think something internal is retaining the connection until it fails or finishes

How to Set Property Value in Objective-C the Right Way

I might've jumped into Objective-C a little too fast and assumed I knew enough about memory management to dive in. Turns out I wasn't.
Fast forward a bit and I've caught up ... for the most part. One of my last remaining questions regards the #property/#synthesize process and setting those values properly.
I've often seen this:
SomeObject *obj = [[SomeObject alloc] init];
self.obj = obj;
[obj release];
It makes sense, but I wonder if this accomplishes a similar enough thing to be an alternative:
self.obj = [[[SomeObject alloc] init] autorelease];
Would that be acceptable anywhere you might set the value of the #property, obj? Or is direct access to the instance variable preferred over both of those in the init method?
obj = [[SomeObject alloc] init];
Thanks.
EDIT: Definitely related question that discusses half of my question. The autorelease part of my question is referenced in one of the answers, but has not been confirmed.
So my questions still remain:
Is autorelease a valid alternative in this situation?
Can autorelease be used this way in the init method, or should the instance variable always be set directly in the init method?
The only difference is that in your first example, obj is released immediately (although it was presumably retained by the self.obj setter). The two examples are effectively the same.
Note that going forward, we can rely on ARC to deal with releasing objects at the appropriate time, so you can write:
self.obj = [[SomeObject alloc] init];
and let ARC worry about where to put the release or autorelease.
Update: You seem to be asking how things are different inside an -init method. The two things you need to be aware of are:
When possible, you should access ivars directly in -init and -dealloc methods. The idea is to avoid problems that could occur if your accessors are overridden by a subclass. There are a number of other questions here on SO that address this in greater depth, such as:
Why shouldn't I use Objective C 2.0 accessors in init/dealloc?
If you're creating an object in an -init method and assigning it to an ivar, you probably don't want to release it until a later point, such as -dealloc. So yes, it's fine in an -init method to not release the objects you create (so long as you keep a reference to them), but you'll still balance that +alloc with a -release in -dealloc.

alloc/release of Objective-C objects

I have Util class as follows.
#implementation Util
- (NSString*) getTodayString
{
NSDate *today = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
// display in 12HR/24HR (i.e. 11:25PM or 23:25) format according to User Settings
[dateFormatter setDateFormat:#"YYYY/MM/dd"];
NSString *now = [dateFormatter stringFromDate:today];
[dateFormatter release]; ///???
[today release]; //???
return now;
}
#end
And I use the class
- (void)awakeFromNib
{
Util *ut = [[Util alloc] init];
NSString* now = [ut getTodayString];
NSLog(#"User's current time in their preference format:%#",now);
[currentTime setObjectValue:now];
[now release]; ///???
[ut release];
}
I'm confused when releasing objects.
In getTodayString ::
Q1. [dataFormatter release] is necessary?
Q2. [today release] is necessary?
I guess I don't need to release them as I didn't alloc myself. If that's true, when those objects are released?
In awakeFromNib ::
Q3. [ut release] is necessary?
Q4. [now release] is necessary?
I guess I have to release ut as I create the object explicitly, but not suer about now object.
How one can determine when is the object is released?
With python/C#/Java one doesn't care about this kind of deallocation of memory anymore. Is it also OK with Objective-C if I don't care about them?
Q1. [dataFormatter release] is
necessary? Q2. [today release] is
necessary?
dataFormatter: yes, you alloc/init'd it.
today: no, it was returned autoreleased from a factory method.
Q3. [ut release] is necessary? Q4.
[now release] is necessary?
The same,
ut: yes, you alloc/init'd it.
now: no, it was returned autoreleased from a factory method.
How one can determine when is the
object is released?
it's released when release is called on it, if autorelease is called, release will be called during the next run of the Autorelease Pool.
Is it also OK with Objective-C if I
don't care about them?
No, it's not ok. If you do not clean up after yourself you will have substantial memory leaks, in the iOS environment that means a quite shutdown of your app. In a Mac app that can lead to eating up a ton of memory and not being a good citizen. This is assuming a non garbage collection environment. Ie most.
I'm guessing the heart of your question is you aren't sure when you are responsible for calling release and when you get an autoreleased object (or rather, when you are responsible for calling release on the object). It's by convention. If you call any method that returns an object that does not contain the words: init/copy then it is not your responsibility to call release. If you retain, you release (There may be some more rules to follow, but that's the first one to really start understanding this, in my opinion). If you ever call alloc/init/copy, then you must call release at some point.
A GREAT teacher is Build & Analyze in Xcode. This will quickly point out where you screwed up and really help to understand what is going on.
Whether or not you care about memory management in objective-c depends on the environment you are using. If you are using garbage collection, you don't have to worry about it, but garbage collection is not enabled by default on the mac and is not available at all on iOS. Basic rules for when something needs to be released:
If the method you get it from starts with alloc or init, or contains the word copy, then you own it and must release it.
If you explicitly retain an object, you own it and must release it.
If the method does not contain alloc, init, or copy, you can assume it has been autoreleased. It will be released automatically at some point in the future, and you need to retain it if you want to use it after the current method returns.
Of course those also depend on any third party code following those rules with when they autorelease returned objects.
The memory management rules are simple and clear. Do not think in terms of retain counts, always think in terms of ownership. When you ask yourself the question “should I release this object?”, ask yourself “do I own it?”. Commit the rules to memory, and eventually they will become second nature.
It is extremely important that you follow the rules. If you ignore them, objects that you don't own may be deallocated before you are done with them (such as assigning objects that you don't own to instance variables, they may become deallocated after the autorelease pool is drained). Also, if you ignore them, you will end up with horrendous memory leaks.

Memory management semantics of Objective C "new"

Is "new" an equivalent of "alloc init" or "alloc init autorelease"?
I cannot seem to find it in any tutorial or article that deals with Cocoa memory management.
Thanks for advise.
How about this one. Read them, understand them, they're simple.
new returns an object with a retain count of 1, just like [[alloc] init]. The object is not autoreleased.
+[NSObject new] is functionally equivalent to +[NSObject alloc] followed by -[NSObject init] (i.e. [[alloc] init]).
To answer your question, from the NSObject class docs:
If you are using managed memory (not
garbage collection), this method
retains the object before returning
it. The returned object is not
autoreleased. The invoker of this
method is responsible for releasing
the returned object, using either
release or autorelease.
Using new is rare in modern Cocoa code. Most Cocoa developers favor explicit, clear code over saving a couple of key strokes. Thus alloc/init is preferred.