Re: Newbie OOP style question
Re: Newbie OOP style question
- Subject: Re: Newbie OOP style question
- From: "Pierce T. Wetter III" <email@hidden>
- Date: Thu, 11 May 2006 17:06:35 -0700
On May 11, 2006, at 4:28 PM, Tim Gray wrote:
Hi, I've just started programming in Obj-C (after a decent amount of
experience in Python) and I've got 2 questions. I'm writing a simple
CLI program that uses NSFilehandle to read in data from a file (in
little endian) and stores it in some variables. Simple enough. I'm
creating a class for these files where I declare said variables. The
plan is to have in instance for each file that is read and instance
variables for the particular attributes that I have for the files.
My question is this: I declare some temporary variables in my class
interface which I use to manipulate the info read from the file into
my Foundation data types (NSString, NSNumber, etc.). Once the info is
stored in the Foundation data types, I don't really need the temporary
variables anymore - are these something I can clear out somehow, or do
I not need to worry about it? Is this also the appropriate way to do
things? I've read through "Programming in Obj-C" by Kochan twice and
am a little freaked out by memory management (I am coming from Python
after all - declaring variables and memory management are strange to
me...).
Er... This is such a big topic, I hardly know where to start.
In both Python and Objective-C, objects are allocated and
deallocated by something called reference counting. That is in
Python, if you do:
A= B
Then behind the scenes, there's a hidden:
obj.referenceCount = obj.referenceCount + 1
(A/B in Python are _references_ to "obj" , all assignments in
Python just pass around the references.)
When you do:
A= NULL
or
del A
or
"A goes out of scope"
then that does:
obj.referenceCount = objc.referenceCount -1
if (obj.referenceCount == 0) delete obj
Now Python does that behind the scenes so you don't have to worry
about it (in theory, in practice, garbage collection can be a royal
pain).
Objective-C uses the exact same mechanism. When the number of
variables "using" an object goes to zero, the object isn't needed any
more so its memory is freed.
The only difference between Obj-C and Python in this regard is that
in Objective-C, you have to explicitly increment the reference
counter and decrement the reference counter.
You do this very simply:
[obj retain]; // increments the counter and returns the object
[obj release]; // decrements the counter, calls dealloc if its zero
So while in Python, you wrote:
A = B;
The equivalent operation in Objective-C would be:
A = [B retain];
Similarly:
A = NULL or del A
is
[A release]
Except that would be an awful lot of retaining/releasing if
everytime you assigned a pointer to an object you also called retain
and then you called release when you were done with it. So instead,
Foundation has something called an "autorelease pool". All an
autorelease pool is is just a list of objects that will eventually
have [obj release] called. These objects are called "autoreleased"
objects, but that really means "delayed release" objects.
All foundation objects end up then with two creation interfaces:
A=[[NSNumber alloc] initWithUnsignedLong: 1]
B=[NSNumber numberWithUnsignedLong]
Both methods create an object with a retention count of 1.
However, object B has been "autoreleased", which means its sort of "1
with 1 release pending". So B will get thrown away automatically,
while A will stick around until someone calls release on it.
What all that means is that if you're making a temporary object,
you can use the autorelease style creation interfaces. Any temporary
object will then automatically be thrown away when the autorelease
pool performs the delayed release (because 1 minus 1 = zero), _unless
someone has "retained"_ it (because 1 + 1 minus 1 = 1). Pretty much
any method that returns an object returns an autoreleased object. Its
up to the _caller_ to retain it because only the caller can know how
long it needs it. The exceptions for methods that return retained
objects are small: init, mutableCopy.
You can also "autorelease" any object by using [obj autorelease]
instead of [obj release], to get the "delayed release" effect.
Ok, so lets go look at your code.
-(void) setFileLengthWithFile: (NSFileHandle *) fileHandle
{
dataBuffer = [fileHandle readDataOfLength:4];
[dataBuffer getBytes: &numBuffer];
numBuffer = EndianU32_LtoN(numBuffer);
fileLength = [NSNumber numberWithUnsignedLong: numBuffer];
}
Not a retain in sight... So dataBuffer and fileLength are going to
get thrown away when the autorelease pool fires.
But really, its just a matter of practice with the idiom:
1. Did you call init? Better call release/autorelease somewhere.
2. Did you get the object from someone else and you need to keep
it around? better call [retain].
3. call [instanceObj release] on every instance variable in your
dealloc method.
Pierce
P.S.
Extra credit:
Accessors are usually written this way:
- (void) setValue: (id) newValue
{
[newValue retain];
[value release];
value=newValue;
}
Why not:
- (void) setValue: (id) newValue
{
[value release];
value=[newValue retain];
}
(Hint: what happens when newValue == value?)
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden