Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Denarius

macrumors 6502a
Original poster
Feb 5, 2008
690
0
Gironde, France
Okay, I'm steadily working through Aaron Hilleglasses brilliant book on Cocoa and have just completed the character count program and it works.
Thing is though, I'm quite keen not to rely on garbage collection and am not sure if I've really understood retaining and releasing properly.

Initially, I thought I should ask it to release typedText and result and the program worked the first time and then hung. Am I right in thinking that NSString objects are dealt with by the NSAutoRelease pool? Other thing I'm not quite sure about is how retain counts relate to IBActions and IBOutlets.

Would be grateful to hear people thoughts and hopefully clear up my own in the process. :)

Code:
#import "CountController.h"


@implementation CountController

- (IBAction)count:(id)sender
{	
	NSString *typedText = [textField stringValue];
	NSString *result = [[NSString alloc]initWithFormat:@"The number of characters in your sentence is %d",[typedText length]];
	[countResult setStringValue:result];
}
@end
 

Mac Player

macrumors regular
Jan 19, 2006
225
0
You can user the method retainCount to check the retain count of an object.

The informal rule of the apple API is whenever you get an object from a method not started with init then I is and autoreleased object.

So in this case [textField stringValue] returns an autoreleased object. And after you set the stringValue you can release the object you created.
 

Enuratique

macrumors 6502
Apr 28, 2008
276
0
Okay, I'm steadily working through Aaron Hilleglasses brilliant book on Cocoa and have just completed the character count program and it works.
Thing is though, I'm quite keen not to rely on garbage collection and am not sure if I've really understood retaining and releasing properly.

Initially, I thought I should ask it to release typedText and result and the program worked the first time and then hung. Am I right in thinking that NSString objects are dealt with by the NSAutoRelease pool? Other thing I'm not quite sure about is how retain counts relate to IBActions and IBOutlets.

Would be grateful to hear people thoughts and hopefully clear up my own in the process. :)

Code:
#import "CountController.h"


@implementation CountController

- (IBAction)count:(id)sender
{	
	NSString *typedText = [textField stringValue];
	NSString *result = [[NSString alloc]initWithFormat:@"The number of characters in your sentence is %d",[typedText length]];
	[countResult setStringValue:result];
}
@end

You don't need to release typedText (since the textfield owns it and will take care of that) and releasing it will cause the program to hang since the textField will then try to use it and it's no longer there. You still need to release result, however.

There is a good article on memory management in Cocoa here that every new Cocoa developer should read before coding.
 

Denarius

macrumors 6502a
Original poster
Feb 5, 2008
690
0
Gironde, France
You can user the method retainCount to check the retain count of an object.

The informal rule of the apple API is whenever you get an object from a method not started with init then I is and autoreleased object.

So in this case [textField stringValue] returns an autoreleased object. And after you set the stringValue you can release the object you created.

Thanks for the tip on the retainCount method. I tried that in an NSLog statement and got the following results.

Code:
NSString *result = [[NSString alloc]initWithFormat:@"The number of characters in your sentence is %d",[typedText length]];
//retain count here is 1
	[countResult setStringValue:result];
//retain count here is 3?!!!
A bit boggled why the second line is hiking the retain count by 2, surely it should be just an increment of 1?

Just one more question though: does the [result release] statement belong in this method or in a class dealloc method? Or even both?
 

Mac Player

macrumors regular
Jan 19, 2006
225
0
Thanks for the tip on the retainCount method. I tried that in an NSLog statement and got the following results.

Code:
NSString *result = [[NSString alloc]initWithFormat:@"The number of characters in your sentence is %d",[typedText length]];
//retain count here is 1
	[countResult setStringValue:result];
//retain count here is 3?!!!
A bit boggled why the second line is hiking the retain count by 2, surely it should be just an increment of 1?

Just one more question though: does the [result release] statement belong in this method or in a class dealloc method? Or even both?

Don't worry too much about how an API call changes the retainCount of your object. Just make sure you properly manage the memory on your side of the code.


Ok now lets look at all the options you have to release the result object:

1. Releasing at dealloc: You can't do that because result is local to your method so it is out of scope for the dealloc method. Even if it were on scope the app would be leaking memory because only the last result would get released.

2. Releasing at the method: This works!! Since you released result the textfield is the only interested on the string. Each time you set a new string value the retain count will be properly decremented by the API method and the memory is freed.
 

Denarius

macrumors 6502a
Original poster
Feb 5, 2008
690
0
Gironde, France
2. Releasing at the method: This works!! Since you released result the textfield is the only interested on the string. Each time you set a new string value the retain count will be properly decremented by the API method and the memory is freed.

Thank you very much sir, I think I may yet get the hang of this (and Enuratique). It seems the compiler sorts out more than I realised.

One final question though, given that the retain count for result is 3 by the end of the method, if I release it once, is that enough for the API to deallocate it when a new string comes along (I hope I'm making sense, apologies if my terminology's sounding a bit wooly).
 

Denarius

macrumors 6502a
Original poster
Feb 5, 2008
690
0
Gironde, France
Actually, I just tried popping in 2 [result release] statements out of curiosity and it crashed, so I guess that answers my question! :)

Thanks again for all your help.
 

Mac Player

macrumors regular
Jan 19, 2006
225
0
If the NSTextField's method incremented the retain count by 2 then the NSTextField's implementation should be responsible for decrementing the string's retain count by 2 whenever an event makes the object uninterested on the string.
 

Denarius

macrumors 6502a
Original poster
Feb 5, 2008
690
0
Gironde, France
If the NSTextField's method incremented the retain count by 2 then the NSTextField's implementation should be responsible for decrementing the string's retain count by 2 whenever an event makes the object uninterested on the string.

Thank you for that, that last comment was particularly helpful. I might come back once I've read this article Enuratique kindly pointed me to and I've confused myself again.

I must admit, I also discovered that I could replace the initWithFormat with stringWithFormat and let the AutoRelease pool get on with it. Seems a bit like cheating though! :D
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.