2

I am trying to copy a string that is passed into a method like so:

-(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
    NSLog( @"elementName, %@:  %i", elementName, [elementName retainCount] ); // rc = 2

    if ( currenttag )
        [currenttag release];

    NSLog( @"currenttag:  %i", [currenttag retainCount] ); // rc = 0

    //currenttag = [[NSString alloc] initWithString:elementName];   // track current element
    [self setCurrenttag:elementName];

    NSLog( @"currenttag:  %i", [currenttag retainCount] ); // rc = 3

    .
    .
    .
    }

setCurrenttag is a synthesized accessor ( @property (copy) ). My understanding was this would create an entirely new object instead just a reference to elementName. The above behaves as though it is keeping a reference to elementName and calling retain. The commented out bit of code shows the same behaviour.

These methods are implementing the NSXMLParserDelegate protocol, but I do need keep a track of certain element names (but not all).

Is there something I am missing concerning NSString objects and memory management on the iphone.

Also, as reference, I am running this on the iPhone simulator with XCode 3.6.

Mike D
  • 4,938
  • 6
  • 43
  • 99
  • If you are concerned about the string not being copied, why don't you check with the pointers of elementName and currenttag? – EmilioPelaez Jul 08 '11 at 19:44
  • 1
    [Do not use -retainCount.](http://stackoverflow.com/questions/4636146/when-to-use-retaincount/4636477#4636477) – Brad Larson Jul 08 '11 at 22:29
  • @Brad Larson Wouldn't the retain count be a quick way to watch for memory leaks? – Mike D Jul 11 '11 at 12:23
  • 1
    @Mike - No. Read what Dave has to say about this at the above link. For a more emphatic response, see this: http://stackoverflow.com/questions/3730804/how-many-times-do-i-release-an-allocated-or-retained-object/3730835#3730835 . Note that both of these people are Apple employees. – Brad Larson Jul 11 '11 at 14:14

6 Answers6

5

For immutable Foundation classes like NSString, copy simply retains the object. Duplicating an object that's known to be immutable would be a waste of resources, so it doesn't happen. This is hinted at in the documentation for the NSCopying protocol. One of the options for implementing the protocol is:

  • Implement NSCopying by retaining the original instead of creating a new copy when the class and its contents are immutable

In general, if you know that instances of one of your classes will be immutable, it's entirely valid to retain the target object rather than duplicate it.

Tom Harrington
  • 69,312
  • 10
  • 146
  • 170
2

Don't count on retainCount to be intuitive. What's likely happening here is that the string in question is not mutable, so a "copy" ends up just retaining the existing string (which is fine since it can never change).

Daniel Dickison
  • 21,832
  • 13
  • 69
  • 89
  • @Damiel Dickison If I understand you correctly, after releasing, I should set currenttag to nil. – Mike D Jul 08 '11 at 19:41
1

Whenever you deal with objects you must never deal directly with the retain counts, you must deal with them only in terms of differences. All you must know is retain is +1 and release is -1

shreyasva
  • 13,126
  • 25
  • 78
  • 101
0

Just a guess, but since NSString is immutable, it might be an optimization that the property does a retain instead of creating a new object.

highlycaffeinated
  • 19,729
  • 9
  • 60
  • 91
0

Don't trust the retainCount. Just release every object for which you called alloc, copy, retain and new.

dasdom
  • 13,975
  • 2
  • 47
  • 58
  • My question is more about properly instantiating a new string. I was using the retainCount for debugging only. I call release when I need to, yet it is not behaving the way Apple's Memory Management guide describes, unless there is special section dealing with strings that I have missed. – Mike D Jul 08 '11 at 19:41
  • Except I need track all the element names as it moves through document hierarchy. I can not have it persist after I call release. – Mike D Jul 08 '11 at 19:47
0

In my experience the retainCount does not always return the actual retain count, and it can be tricky. NSString is an immutable object, so it might behave differently than other objects, I am not sure if Objective C implements a String pool like java does, since it doesn't mention so in the documentation.

Oscar Gomez
  • 18,436
  • 13
  • 85
  • 118