4
#define kTestingURL @"192.168.42.179"

...

NSString *serverUrl = [[NSString alloc] initWithString:
                        [NSString stringWithFormat:@"http://%@", kTestingURL]]; 
NSLog(@"retain count: %d",[serverUrl retainCount]);

Why is the retain count 2 and not 1?

Man of One Way
  • 3,904
  • 1
  • 26
  • 41
  • 2
    This page might provide some insight: http://stackoverflow.com/questions/5784084/calling-retaincount-considered-harmful – Monolo Jul 26 '11 at 14:33
  • Everyone who asks a question about retainCount should either give me a nickel or +1 the question and the answer in that post that @Monolo linked. – Joe Jul 26 '11 at 14:36
  • 4
    [Don't use -retainCount](http://stackoverflow.com/questions/4636146/when-to-use-retaincount/4636477#4636477). Thankfully, under ARC, using `-retainCount` now throws a compiler error. – Brad Larson Jul 26 '11 at 14:40
  • possible duplicate of [Creating a new NSString instance has retain count of 3](http://stackoverflow.com/questions/6629435/creating-a-new-nsstring-instance-has-retain-count-of-3) – Brad Larson Jul 26 '11 at 14:47
  • I didn't even know it existed before code completion kept suggesting it when I typed `retain`. I blame that feature for the confusion. – Monolo Jul 26 '11 at 14:50

4 Answers4

5

Yes, You will get retain Count 2, one for alloc and other for stringWithFormat. stringWithFormat is a factory class with autorelease but autorelease decreases retain count in the future.

iCoder4777
  • 1,682
  • 1
  • 14
  • 35
  • 2
    Wait, what? `stringWithFormat` returns an auto-released object, sure, but here it is being passed as a parameter to `initWithString` on another instance. As such, that other instance should not reflect the retain count of the anonymous object created by the inner called to `stringWithFormat`. Of course, it **may** be that `initWithString` just retains the other string and discards the allocation as an optimisation in some cases, but this is *inside the abstraction*, and should not be considered as behaviour you can rely upon. – Adam Wright Jul 26 '11 at 14:54
  • @Adam "this is *inside the abstraction*, and should not be considered as behaviour you can rely upon" nor should be the absolute value of the retain count. – albertamg Jul 26 '11 at 14:58
  • @Monolo The documentation actually says it copies character by character. I'm saying it may choose to do something else *if* it can be certain the observable behaviour (up to Cocoa conventions) will be the same. However, you should not rely on it (I've no idea what it does internally - it's an abstraction!). – Adam Wright Jul 26 '11 at 15:17
5

You shoud not care about the absolute value of the retain count. It is meaningless.

Said that, let's see what happens with this particular case. I slightly modified the code and used a temporary variable to hold the object returned by stringWithFormat to make it clearer:

NSString *temp = [NSString stringWithFormat:@"http://%@", kTestingURL];
// stringWithFormat: returns an object you do not own, probably autoreleased
NSLog(@"%p retain count: %d", temp, [temp retainCount]);
// prints +1. Even if its autoreleased, its retain count won't be decreased
// until the autorelease pool is drained and when it reaches 0 it will be
// immediately deallocated so don't expect a retain count of 0 just because
// it's autoreleased.
NSString *serverUrl = [[NSString alloc] initWithString:temp];
// initWithString, as it turns out, returns a different object than the one
// that received the message, concretely it retains and returns its argument
// to exploit the fact that NSStrings are immutable.
NSLog(@"%p retain count: %d", serverUrl, [serverUrl retainCount]);
// prints +2. temp and serverUrl addresses are the same.
albertamg
  • 28,492
  • 6
  • 64
  • 71
2

You created a string and then used it to create another string. Instead, do this:

NSString *SERVER_URL = [NSString stringWithFormat:@"http://%@", kTestingURL];
Peter DeWeese
  • 18,141
  • 8
  • 79
  • 101
  • But why does serverUrl (sorry about me editing the instance name) get 1 extra retain count just because of the second NSString? That string should be autoreleased or something? – Man of One Way Jul 26 '11 at 14:35
  • 1
    He did do this, but it doesn't explain why `serverUrl` would have a retain count of two (he would expect it to have a retain of 1, as it's freshly constructed with the *value* in another string). The real answer is that, outside of a few scenarios, one shouldn't expect `retainCount` to reflect exactly the number of `init` and `retain` calls *your code* has made. – Adam Wright Jul 26 '11 at 14:37
  • Okey, but I also want to release it later on, is that possible using your creation of the serverUrl? – Man of One Way Jul 26 '11 at 14:40
  • Well put @Adam Wright. Something other than your code can also retain, and it is usually useless to look at the retain count. Instead, one should make sure that their own code follows proper memory management rules. – Peter DeWeese Jul 26 '11 at 14:44
  • @Man of One Way, it will be released as needed. For all but a few apps autoreleasing strings will not cause performance problems. – Peter DeWeese Jul 26 '11 at 14:46
1

this is because you [[alloc] init] a first NSString so serverUrl have retain +1 and at the same line you call [NSString stringWithFormat] that return another nsstring on autorelease with retain count at 2 you should only use the :

NSString *serverUrl = [NSString stringWithFormat:@"http://%@", kTestingURL];

so your serverUrl will have retainCount to 1 and you don't have to release string