Question on retain counts.

Discussion in 'Mac Programming' started by Denarius, Jul 9, 2008.

  1. Denarius macrumors 6502a

    Denarius

    Joined:
    Feb 5, 2008
    Location:
    Gironde, France
    #1
    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
    
     
  2. Mac Player macrumors regular

    Joined:
    Jan 19, 2006
    #2
    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.
     
  3. Enuratique macrumors 6502

    Joined:
    Apr 28, 2008
    #3
    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.
     
  4. Denarius thread starter macrumors 6502a

    Denarius

    Joined:
    Feb 5, 2008
    Location:
    Gironde, France
    #4
    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?
     
  5. Mac Player macrumors regular

    Joined:
    Jan 19, 2006
    #5
    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.
     
  6. Denarius thread starter macrumors 6502a

    Denarius

    Joined:
    Feb 5, 2008
    Location:
    Gironde, France
    #6
    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).
     
  7. Denarius thread starter macrumors 6502a

    Denarius

    Joined:
    Feb 5, 2008
    Location:
    Gironde, France
    #7
    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.
     
  8. Mac Player macrumors regular

    Joined:
    Jan 19, 2006
    #8
    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.
     
  9. Denarius thread starter macrumors 6502a

    Denarius

    Joined:
    Feb 5, 2008
    Location:
    Gironde, France
    #9
    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
     

Share This Page