What is retainCount in Objective-C? - objective-c

I have a UITableView as my first screen with a UINavigation controller.
In my first screen I NSLog(#"Home Screen retain Count=%d",[self retainCount]); and it logs 6 in when its viewDidLoad is called.
Is this correct?

The retainCount is the number of ownership claims there are outstanding on the object.
You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. All of these increment the retainCount.
You relinquish ownership with using “release” or “autorelease”. These decrement the retainCount.
However you should never pay any attention to the value of retainCount, it is at best confusing, at worst misleading. Simply follow the memory management rules - take ownership when you need to keep a reference to an object and relinquish ownership when you are finished, and you wont have a problem.
If you are looking at retainCount, you are going about things the wrong way, and you will simply confuse yourself further.

It sounds fine. Why would it be wrong?
In general, trying to determine things from the retain count is a bad idea. There are no rules about the amount of times you can retain an object. The only rule is that each retain must be balanced with a release.

Related

Leaking objects, and I need to fix it

I'm importing some older ObjC code, circa 2006, to the latest Xcode. It was written before the era of ARC, and I don't have a strong handle on the previous system. Looking for some advice on how to diagnose these.
Here's an example, one of hundreds...
sym = [ globals addObject:[ [ NCObject alloc ] initWithArray:saved dimension:dimension type:type ] ] ;
The error isn't specific, do I need an autorelease around the entire thing, or one immediately after "type ]"?
I seem to recall that the basic rule is that if I see an inti, I need to autorelease it. Are there other cases I need to think about?
Yes. Autorelease is right. The alloc creates an rc=+1 object. Adding it to the array makes it +2. Autorelease will leave it at +1, which is where you want it. Releasing the globals array eventually will bring it back to 0, which is also desired behavior.
For clarity:
sym = [[NCObject alloc] initWithArray:saved dimension:dimension type:type];
[globals addObject:sym];
[sym autorelease];
Note that release is just as good in this case (a little better because it doesn't leave any autorelease pool work for later). Unless the function returns sym, you can release.
alloc... (any method that starts with alloc), new, copy..., mutableCopy... give you retained objects (thanks to #jlehr for extending the original list).
Collections retain
objects that are contained in them (in your case, globals retains
that NCObject that you create.
You should balance every retain
that you write with a release or autorelease. If you release an object, you can't use it anymore, because if its
retainCount has reached zero, it will be deallocated instantly. An
autoreleased object will live until the nearest autoreleasepool
drain.
In the example that you wrote, you either have to balance an alloc, so you have to either release your NCObject after you've added it to the array (if you release it before that, it will most likely be deallocated), or autorelease it whenever you want.
But I would really recommend you to read Apple's Advanced Memory Management Programming Guide. It's short. And it describes all the rules that you'll need.

Dealloc method isn't called when i release perticular object

I have created an object using alloc/init method, and after I release it -dealloc should be called immediately as per documentation. I set a breakpoint on -dealloc method but it isn't hit, and my -dealloc method is not called.
Please tell me what is the reason behind that, and what is use of dealloc method in objective c ?
The -dealloc method is not always called when you expect it to be called. The runtime might also have issued a -retain on your object for internal reasons.
It's also possible that you have (directly or indirectly) caused an extra -retain to be issued. If the retains/allocs and releases are not balanced, you'll never see -dealloc called. It helps to turn on the Static Analyzer, to make sure your calls balance.
Just follow the memory management rules, don't second guess the runtime, and let the memory management system do its job.
The answers to When does dealloc method call? may help you understand what you're seeing.
because it still has reference. that means its reference count not reached to zero. i don't know your code, where it is referencing. but it is not calling that means somehow still it has reference. it may be because of strong relationship or parent-child relationship
all Objective-C objects are allocated on the heap, so they must
therefore be deallocated somewhere if you are not to run out of
resources.
This gave way to the reference counting method, which is still used
today: each object keeps count of any references held to it. If you
receive an object and you want to keep it, you retain that object,
incrementing its reference count. When you are done with it, you
release it, which decrements its reference count. Once that count
reaches zero, it is inferred that no one is referencing the object and
it is automatically deallocated using the -dealloc method.
Additionally, an object could be told to “release at some point in the
(hopefully) near future” using autorelease pools. The idea is that
somewhere on the stack (typically at the start of a thread or while
responding to input events) an autorelease pool is created and pushed
onto a stack. Any object can then be sent an -autorelease message, and
it is assigned to that pool.
When the pool object is deallocated, it simply sends a -release
message to all its assigned objects. That way, any objects that are no
longer used (i.e. they haven’t been explicitly retained) are then
deallocated.
The dealloc is called (at more cases) whenever your object is released. You can't directly call this method.
#interface myViewController:UIViewController
{
NSString *myStr;
}
#end
Here the dealloc method in the #implementation of myViewController will be called (at most cases) when the myViewController object is released, not when myStr is released.
Although you don't have to use if you ARC.

How does retainCount work?

I have a problem with retainCount
NSLog(#"%i", [self.albumReceiver retainCount]);
self.albumReceiver = [[[FacebookAlbumsDelegateReceiver alloc] init: self] autorelease];
NSLog(#"%i", [self.albumReceiver retainCount]);
The retain count on the first line is 0 but when it gets to third line is 3.
The property on self.albumReceiver is retain property... But as far as i can see it should be 2 where other later retain count should went to 1 since it was autorelease later.
NSLog(#"%i", [self.albumReceiver retainCount]);
albumReceiver = [[[FacebookAlbumsDelegateReceiver alloc] init: self];
NSLog(#"%i", [self.albumReceiver retainCount]);
the retain count start with 0 and in this case the second retain count print 2....
Can somebody give some idea of how this retain and release work....
I thought without 'self' keyword, it will ignore the setter call is it? But if i put autorelease on the second example, i will have error.
Firstly, the retain count is an implementation detail that you should not be overly concerned with. You should really only care about ownership.
Having said that, the explanation for what you are seeingis as follows:
The retain count on the first line is 0
That's because self.albumReceiver is nil at that point. On real objects, you will never see a retain count of 0 (in the current implementation of Foundation).
when it gets to third line is 3
Normally you would expect the retain count to be 2, +1 for the alloc and +1 for assignment to a retain property. However, the init: method might cause some other object to retain it, so might the setter for the property. Another object observing the property might choose to retain the object too. In short, unless you know the exact implementation of all the methods involved and you know for sure nothing is using KVO on albumReceiver, all you can say about the retain count is that self has ownership of it (NB ownership is not exclusive, other things may also have ownership). This is why you shouldn't pay too much attention to retain counts.
Can somebody give some idea of how this retain and release work
Yes. You need to think in terms of ownership. Certain methods give you an object that you own. These are any method starting with alloc, any method starting with new, any method starting with copy or mutableCopy and -retain. If you receive an object in any other way, you do not own it. That includes receiving them as a return result of a method, ass parameters of a method or as by reference parameters of a method or as global or static variables.
If you own an object, you must relinquish ownership by either releasing or autoreleasing it, or it will leak. If you do not own an object, you must not release or autorelease it.
I find that it is best to think of "you" in the above as meaning "the scope in which the object reference was declared".
Anyway, I recommend you to read Apple's Memory Management Rules for the definitive explanation and not to trust answers here. If you look at the original edit for this answer, you'll see that I got the rules slightly wrong because they have been tightened up since I last read them.
Do not use retainCount. (For situations where it’s appropriate to use it, see this website.) Further reading: blog post by bbum, previous SO thread one, thread two. Also note that retainCount is deprecated in recent SDKs. It’s a good idea to pay attention to the deprecation warnings, and even better idea to turn all warnings into errors.
It is generally a bad idea to pay any attention to the retainCount of an object in Objective-C because it is usually impossible to know which secret parts of the frameworks feel a need to retain the object.
In the case you cite where you are adding the object to the autorelease pool, the autorelease pool will presumably be retaining the object until it comes time to flush the pool (during the runloop). This probably explains why the retain count is higher for the autoreleased object.
Note the use of the words "presumably" and "probably" in the above paragraph. I have no idea if this is actually what is happening inside the Cocoa/Cocoa Touch frameworks. This is the problem with using retainCount, you have no way of knowing what the retain count should be at any moment.
If you retain the object (or create it with a method name that contains alloc, copy, mutableCopy or new), you release it. The frameworks are free to also retain the object and they will release it when they are ready. When the retain count reaches zero it will be dealloced.
Update: Having looked at the GNUStep source code for NSObject and NSAutoreleasePool my possible explanation above probably isn't what is happening. However, I have no way to check for sure because I can't see Apple's implementation of these two objects. Even more reason not to trust retainCount or any inferences from it.
The only rule that really exists in environments with manual memory management is
If you use alloc, copy, mutableCopy, new
release it. Otherwise DON'T. retainCounts don't really work for debugging. See here

Conditions in which retainCount increases or decreases

I have read that objects retain count and that it can be increased when we assigned a second value (or object).
Can anybody give me an idea about the basic conditions where retainCount increases or decreases (without retain , alloc and release)...
Short answer: no.
Slightly longer one:
Actions on your part that are typically expected to modify the retain count are retain, release, autorelease and calling methods whose name contains new or copy. In some instances, however, they might not do so, for good implementation reasons, but do something else instead. And there are many other things you can do, like adding objects to collections, that may modify the retain count in ways that are just not your business.
Do not use or rely on retain counts. They are an implementation detail.
Your concern is to manage your own ownership, which you do via the semantics of the above-mentioned methods. How that affects the retain count beneath the hood is something you are better off not even looking at.
Please just don't.
Being concerned about retain count is almost always a way to cause bugs, not cure them.
The retain count of an object is an implementation detail that you shouldn't worry about. You should really only concern yourself with when you gain and lose ownership of an object. Here's why:
+alloc returns an object with a retain count of 1. However, you immediately send it an init message which might give you back a completely different object. For instance
NSString* foo = [[NSString alloc] initWithString: #"foo"];
Gives you an object with a retain count of 1, right? Wrong on current implementations of Cocoa. The string returned by +alloc is immediately released and instead a reference to #"foo" is returned. The retain count of #"foo" is INT_MAX.
Retaining an object increases its retain count, right? Probably, but again sending retain to constant strings has no effect and some singletons have a nul implementation of retain too.
Similarly release usually has an effect on the retain count, but again not necessarily for the same reasons.
Sending copy should give you a new object with a retain count of 1 right? Wrong. Immutable objects can implement copy by sending themselves retain and then returning themselves. In most cases, that will add one to the retain count, but of course with string constants, nothing happens.
If you just think in terms of retaining and releasing ownership all of that stuff I have just said becomes irrelevant implementation details.
retainCount of an object changes in the following cases:
When you create an object(new or
alloc, copy or mutablecopy), it has a
retain count of 1.
When you send an object a retain
message, its retain count is
incremented by 1.
When you send an object a release
message, its retain count is
decremented by 1.
When you send a autorelease message
to an object, its retain count
will be decremented by 1(not
immediately as in case of release but
some time in the future)
You can view this post to get a detailed info on how memory management works in iPhone.

Retain count and dealloc in iPhone

I want to ask about the iPhone application and objective C question. In the implementation program, there are function called 'dealloc', does this function only be called one time by the application?
For example, if I alloc a object and retain it 2 times, the retains count is 2 and I never use 'release' in the program, unless in the dealloc. Will the object be removed from the memory, or the objective will be removed from the memory. Thank you.
In the implementation program, there are function called 'dealloc', does this function only be called one time by the application?
Yes. -dealloc destroys the object. Trying to send any message to it again, including -dealloc is an error.
if I alloc a object and retain it 2 times, the retains count is 2
Careful. The retain count is at least 3. Other things than your code might retain the object. It's better not to worry to much about retain counts and only think in terms of ownership.
Each alloc, new, copy or retain is an claim of ownership. The object's dealloc method will only be called when all claims of ownership have been relinquished. A claim of ownership is relinquished by sending -release. So if you never release an object except in its own dealloc, you'll never release it.
dealloc is called once by the system when the object is destroyed (when its reference count reaches 0). If you have member variables in your class that you alloc in your init function, you must release them in your dealloc function.
If you give someone a pointer to one of those member objects and they retain it, the member could survive the release in your dealloc, but by sending a retain message they are taking responsibility for sending a release message later, ensuring its eventual destruction.