Quite the catchy title, eh??
I have been looking into some memory management techniques in Objective-C. I’m used to the way C/C++ and many other languages do it, by using the “new” keyword.
In Objective-C, this is done differently.
While you CAN declare a class variable like this:
myClass *object = new myClass;
it is not the most common way. Instead, its more commonly seen like this:
myClass *object = [[myClass alloc] init];
The “new” keyword allocates a space in memory to hold the object. It then initialises it, probably with a constructor and can give variables a default value. So thats 2 things it does. Allocates and initialises. In Objective-C, these are done independantly.
Also, note the nesting of the square brackets. Its making 2 calls, but just doing it in a more readable way.
I mentioned constructors above, and I’ll show you now how to pass a variable to the “constructor”. Note, I don’t think they’re actually called constructors and destructors outside C++, but just go with it anyway…. 😉
So, in C++, you would create an object and initilise some string/variable like so:
myClass *myObj = new myClass(“Hello World”);
In Objective-C:
myClass *myObj = [[myClass alloc] initWithString:@”Hello World”];
See how we are initialising with a string? This can also be done with contents of a file or URL, as well as many other options (In XCode, press ESC to see a list when it prompts for auto-completion). For example,
myClass *object = [[myClass alloc] initWithFormat:@”Hello, my name is %@ and I am %d years old”,name, age];
Obviously you also need the back-end to handle these initialisations.
Autorelease Pools
Lets say you create an object that contains a method which in turn creates a new object called myAddress, assigns it a value, then return this value, eg “return myAddress”. You will obviously have to release this object to obey proper memory management rules. Since you need to do your tidy up before calling the “return”, how can you destroy the object but still use it on the next code line without getting a compile error? In Objective-C, we use [myObject release] instead of “delete myObject” like in C++. For example, in C++ pseudocode:
main { myClass *obj1; myClass *obj2 = obj1.returnAddress(); } myClass obj1::returnAddress { myClass *myAddress = new myClass("123 City Road"); delete myAddress; return myAddress; // Will cause error }
So, instead of delete myAddress, Objective-C would read [myAddress release]. Now, stay with me here for a minute while I explain the answer to this problem! Objective-C has the “Pool”, which is like a queue of objects that need to be deleted. When you release an object, it gets deleted straight awat. Now, if you use the “autorelease” keyword in place of “release“, you’ll see some magic happening. You see, autorelease puts the object into the pool for deletion but indicates that its still needed for the moment. The Pool will simply wait a few milliseconds and then just go ahead and delete it. The thing here that I am uncertain about is if it just takes a guess and deletes it whenever, or if it watches the object to wait until it goes out of scope. I’d imagine the latter is how it happens, but I’ll need to look into it. Here’s the corrected code in Objective-C(note the return type in the brackets):
-(myClass) returnAddress { myClass *myAddress = [[myClass alloc] initWithString:@"123 City Road"]; //[myAddress release]; // Will cause the return statement to crash [myAddress autorelease]; // Works fine return myAddress; }
Destructors
We saw above how to initialise data types in constructors, using the initi keyword. Now I want to quickly show you destructors.
The default destructor is always called “dealloc” and is also always predefined, in case you don’t supply your own. Since its already defined in the header file “Foundation.h”, in Objective-C we need to tell the compiler which one we want to use, so it doesnt get confused. This is done with the “super” keyword. See below:
-(void) dealloc {
// Clean up
[super dealloc];
}
And there you go!