0

I am using NSNumbers throughout my app (non-ARC) using different syntaxes. Just to be a little more informed, I tried to see how NSNumbers are retained depending on their initialization syntaxes. So I did the following:

NSNumber* a = @1;
NSNumber* b = [[NSNumber alloc] initWithInt:2];
NSNumber* c = [NSNumber numberWithInt:3];

NSLog(@"%d | %d | %d", a.retainCount, b.retainCount, c.retainCount);

This code fragment is executed with a button tap, and the output has perplexed me (repetitive taps) :

73 | 27 | 6
78 | 159 | 22
78 | 160 | 22
78 | 161 | 22
78 | 162 | 22
78 | 163 | 22
85 | 169 | 22
85 | 170 | 22
85 | 171 | 22
85 | 172 | 22

Now this does not really have a purpose (at least not in my case), but I would like to know how these NSNumbers get to these retain counts.

n00bProgrammer
  • 4,261
  • 3
  • 32
  • 60
  • See http://stackoverflow.com/questions/656902/why-has-nsnumber-such-strange-retaincounts/656935#656935 – paxdiablo Apr 26 '14 at 08:00
  • 2
    I just did. Also [bbum's blog](http://www.friday.com/bbum/2011/12/18/retaincount-is-useless/), and the official documentation. Feel silly now. – n00bProgrammer Apr 26 '14 at 08:02

2 Answers2

6

You should never use retainCount. NEVER. look here

Andrey Chernukha
  • 21,488
  • 17
  • 97
  • 161
  • 1
    It's not dangerous to print it in output. Of course `while (0 != obj.retainCount) [obj release]` is totaly wrong. – Cy-4AH Apr 26 '14 at 09:00
  • did you read the link that i've provided? it says NEVER. never means absolutely never. – Andrey Chernukha Apr 26 '14 at 09:05
  • Downvote for downvote. If Stephen Darlington is yours objective-C good and guru, than you should never use it. And btw I also doesn't use `retainCount`, not because somebody told me never use it, but because I don't need it. – Cy-4AH Apr 26 '14 at 09:09
  • downvote for downvote? downvote not because my answer is bad, but just because you took offense? come on, are you serious? – Andrey Chernukha Apr 26 '14 at 09:11
  • why do you think so? and if you think i'm not right, then why did you say "downvote for downvote"? – Andrey Chernukha Apr 26 '14 at 09:12
  • You can freely print retainCount. For example for looking for memory leaks. And from the start I wasn't going to downvoting yours answer. – Cy-4AH Apr 26 '14 at 09:13
  • 1
    You CAN NOT print retainCount because it won't give you any useless information. are you telling me you understand it better than those who wrote the framework? They say NEVER. – Andrey Chernukha Apr 26 '14 at 09:15
  • i will, don't worry. but you didn't. you're saying that i'm wrong but you can't prove it. – Andrey Chernukha Apr 26 '14 at 09:17
  • Downvote because retainCount is surely an extremely useful debugging tool. Did you ever use Instruments to track a memory leak? It's important to let people experiment. – Gwendal Roué Apr 26 '14 at 10:27
  • @GwendalRoué Did you read the link that i've provided? It says NEVER. Are you telling me these guys don't know what they're saying? They say never and i believe them and everybody do, because they wrote the framework and they know what they're talking about – Andrey Chernukha Apr 26 '14 at 10:30
  • 3
    Yes. This is cargo cult programming. No understanding, and plain application of authority arguments. As a matter of fact, memory is managed by retain count. Retain count must be understood in order to control memory management. Retain count is not taboo, and is not forbidden. People must feel comfortable with retain count. It is normal they experiment with. – Gwendal Roué Apr 26 '14 at 11:00
  • Oh... there's no understanding there by people who wrote the framework, but you (of course) have complete understanding... don't you see it's ridiculous? – Andrey Chernukha Apr 26 '14 at 11:05
  • 1
    Of course they understand it well. This does not mean you should not. – Gwendal Roué Apr 26 '14 at 11:22
  • A link to Apple documentation where retainCount is managed by the developer (jump to "Creating a Singleton Instance" paragraph): https://developer.apple.com/legacy/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32 No, really, retainCount is not beyond developer's control. – Gwendal Roué Apr 26 '14 at 11:32
  • @GwendalRoué Important: This document may not represent best practices for current development. Links to downloads and other resources may no longer be valid. – Andrey Chernukha Apr 26 '14 at 11:34
  • 9
    @GwendalRoué no, really, don't use retainCount. The returned value is meaningless in all but the most contrived circumstances. It is not a useful debugging tool. The count in Instruments is passingly useful only because Instruments also shows the backtrace of every retain, release, and the threads therein. Without that additional info, the absolute retain count is meaningless. – bbum Apr 28 '14 at 14:45
  • 1
    I think this question itself is a great example that retainCount is meaningless and (effectively) unpredictable even in the context of the most simple code. – wjl Apr 28 '14 at 15:28
  • @wjl, it's not meaningless. For example I noticed, that b is not released. – Cy-4AH Apr 28 '14 at 18:06
  • @2 is probably cached in a pool of potentially immortal NSNumber objects. However, retainCount doesn't teach you about that, and in fact misleads you to believing you're leaking @2. How was retainCount useful? – wjl Apr 28 '14 at 18:25
  • 3
    @Cy-4AH The retain count can't tell you if an object is released or not; the retainCount method can never return 0, for example. Nor does it reflect the autoreleased state of an object. – bbum Apr 28 '14 at 19:25
  • 1
    @bbum, may be you mean: the retain count can't tell you if an object is deallocated or not? – Cy-4AH Apr 29 '14 at 04:53
  • @Cy-4AH Thanks; yeah. To expand: *The retain count can't tell if you the object was autoreleased. Nor can the retain count ever tell you if the object was deallocated.*. – bbum Apr 29 '14 at 07:10
2

In Objective-C, retainCount is the number which controls the lifespan of an object. The object remains alive until the retainCount turns 0, and then the object gets deallocated. This is the big picture, with many exceptions, but this is the rule that applies here.

Those retain counts mean that those numbers are used somewhere in your application. Some other objects have retained them. Since your own code does not, this means that some other system objects do.

We'll profile your application with the "Allocation" instrument, and see what it can tell us. Here is the code we'll run:

NSNumber* a = @1;
NSNumber* b = [[[NSNumber alloc] initWithInt:2] autorelease];
NSNumber* c = [NSNumber numberWithInt:3];

NSLog(@"%d | %d | %d", a.retainCount, b.retainCount, c.retainCount);

[[[UIAlertView alloc] initWithTitle:@"number b"
                            message:[NSString stringWithFormat:@"address: %p, retainCount: %d", b, b.retainCount] delegate:nil
                  cancelButtonTitle:nil
                  otherButtonTitles:nil] show];

This alert will tell us what is the address of the number. Instrument will let us track this object's life.

Let's choose the Debug configuration in the profile setup of our scheme. Let's check the "Record reference count" in the "Allocations" instrument options. And see what we can get.

enter image description here

enter image description here

See? This number is indeed used by many system frameworks. Now you know why it has such a big retain count :-)

Gwendal Roué
  • 3,949
  • 15
  • 34
  • 3
    Note that the behavior will change from system to system and platform to platform. Specifically, which numbers are implemented as singletons is an implementation derail. – bbum Apr 28 '14 at 14:47
  • Yet this answers the question: "I would like to know how these NSNumbers get to these retain counts." – Gwendal Roué Apr 28 '14 at 18:20
  • And no up vote neither, due to the "don't event think of retain count" policy. Despite a honest answer to a honest question. – Gwendal Roué Apr 29 '14 at 01:52
  • 1
    Partially; the point of StackOverflow is to educate. Given all the issues surrounding the use of `retainCount`, an answer that doesn't warn the questioner about the dangers therein is incomplete. However, the detailed advice about using the Allocations Instrument to track these events is certainly over and above. – bbum Apr 29 '14 at 04:18
  • 1
    @bbum I'm pretty sure "implementation derail" is an autocorrection, but I'm using it from now on to describe bugs caused by violating abstractions. – jemmons Apr 30 '14 at 16:53