removeObjectForKey: doesn't call dealloc - objective-c

I was under the impression that removing an object from an NSMutableDictionary using removeObjectForKey:#"someKey" released the object being removed. However, the dealloc method of my objects is not being called when I do this. Do I have to explicitly release them? Thanks for any help.

removeObjectForKey will call release -- assuming, of course, that your #"someKey" does actually match an object in the dictionary. However, calling release doesn't guarantee that the object will then get dealloc-ed. It depends what other ownership claims there are on it.
Since in this case the dealloc message isn't getting sent, we can conclude that something else has a continuing claim. This may or may not be the result of an error -- for example, if you have also passed the object to some system component, it might quite legitimately want to keep your object around longer than you do.
If that isn't the case, the most likely cause would be having done something along these lines:
[dictionary setObject:[[SomeClass alloc] init] forKey:#"someKey"];
That is, never relinquishing the initial ownership granted by alloc. Instead this ought to be done something like:
[dictionary setObject:[[[SomeClass alloc] init] autorelease] forKey:#"someKey];

Related

How to Set Property Value in Objective-C the Right Way

I might've jumped into Objective-C a little too fast and assumed I knew enough about memory management to dive in. Turns out I wasn't.
Fast forward a bit and I've caught up ... for the most part. One of my last remaining questions regards the #property/#synthesize process and setting those values properly.
I've often seen this:
SomeObject *obj = [[SomeObject alloc] init];
self.obj = obj;
[obj release];
It makes sense, but I wonder if this accomplishes a similar enough thing to be an alternative:
self.obj = [[[SomeObject alloc] init] autorelease];
Would that be acceptable anywhere you might set the value of the #property, obj? Or is direct access to the instance variable preferred over both of those in the init method?
obj = [[SomeObject alloc] init];
Thanks.
EDIT: Definitely related question that discusses half of my question. The autorelease part of my question is referenced in one of the answers, but has not been confirmed.
So my questions still remain:
Is autorelease a valid alternative in this situation?
Can autorelease be used this way in the init method, or should the instance variable always be set directly in the init method?
The only difference is that in your first example, obj is released immediately (although it was presumably retained by the self.obj setter). The two examples are effectively the same.
Note that going forward, we can rely on ARC to deal with releasing objects at the appropriate time, so you can write:
self.obj = [[SomeObject alloc] init];
and let ARC worry about where to put the release or autorelease.
Update: You seem to be asking how things are different inside an -init method. The two things you need to be aware of are:
When possible, you should access ivars directly in -init and -dealloc methods. The idea is to avoid problems that could occur if your accessors are overridden by a subclass. There are a number of other questions here on SO that address this in greater depth, such as:
Why shouldn't I use Objective C 2.0 accessors in init/dealloc?
If you're creating an object in an -init method and assigning it to an ivar, you probably don't want to release it until a later point, such as -dealloc. So yes, it's fine in an -init method to not release the objects you create (so long as you keep a reference to them), but you'll still balance that +alloc with a -release in -dealloc.

why does release return (oneway void) but autorelease return (id)?

If I do this-
SomeObject* someObject = [[SomeObject alloc] init];
[[someObject release] release];
I presume my program wouldn't crash because the second over-release is acting on nothing.
Whereas
[[someObject autorelease] autorelease];
would crash because the object is released twice by being passed down the chain.
This is a matter of curiousity only, I guess I've never had a problem with it so far.
(See this answer for an explanation what oneway does.)
Your first example doesn't even compile, as void != nil. But if you simply call release two times on an object that has a retain count of 1, it'll for sure crash.
As for why release returns void while autorelease returns id: The first says I don't need this object any more, you may get rid of it. Thus, if it would return something and you would operate on it you're likely to operate on a dead object. By contrast, autorelease more or less says "Soon I won't be needing the object any more but let it stick around until I'm done with the current method."
So as you see they are similar in that they say I won't be needing this object any more, but they differ in the time: release says "you can get rid of the object now", while autorelease says "you may get rid of the object later".
I suppose this is mainly done for ease of use, as one could of course do without (and put every autorelease on its own line):
Whenever you release an object, you're done with it (or at least you should be). There is no need to return the object as it may well have been destroyed already and in any case the caller should not work with the object if it is not yet destroyed (i.e. someone else has a reference to it).
On the other hand autorelease is often used in conjunction with init/alloc and just marks the object for later destruction. Whenever using autorelease one can almost be sure that the object is being used afterwards. Whether you directly return it or work with it on your own (e.g. after [[[SomeClass alloc] init] autorelease]) it is very handy to have the object returned as it saves an explicit line of code for autorelease. It is also helpful to have the autorelease directly in the same line: On return [someObject autorelease] you can directly see, that this is an autoreleased object. If you use it with init/alloc you can directly see that this object does not need another release.
I believe, you've answered your question yourself. Call to autorelease can be in the very beginning of object's life, so probably you'll need to save some code lines by the following statement:
[anotherObject callMethodWithArg: [myObject autorelease]];
Indeed, that's helpful. However, you call a release, in the very end of the code, that uses your object. By saying immediate release, you are saying you don't need this object here anymore. So there's no sense in reusing it's instance. Another option is, that a release call can actually deallocate the object immediately, so returning an invalid pointer will not be a good idea =)

Was the object will survive even I areleased it once

I am trying to know about release keyword. I allocated it once, and then I released it. then also the message was passed to that object. And it gives me output. But the retain count is zero. What is the reason behind this?
MyClass *obj=[[MyClass alloc]init];
[obj release];
[obj WhoAreYou];
I given "NSLOG(#"It is the problem.");"
I got the out put: It is the problem.
See this link..a simple tutorial on memory management..It says
You can think of release as saying
relinquish ownership of this object,
rather than destroy this object
That means when you release you are just losing your control over the object..You are not releasing it..Cocoa will release the variable if it is not referenced by anyone else

Reference on when to release in Objective-C

I'm having a recurring problem in Objective-C. I'm either releasing things too many time, or not enough. or perhaps I'm not retaining them enough...
Can someone point me at a good reference that will give me a rule of thumb on when I need to retain and release?
For example:
I remember reading somewhere that some objects come pre-retained, so I need to release them, but not retain them. Which objects are these?
if I alloc an object and only need it in that method, do I need to release it? retain it?
Obviously, if I retained something, I needtorelease it, but beyond that, I get a bit lost.
The rules are generally pretty simple. If you get an object in one of the following ways:
id obj = [[MyObject alloc] init];
id obj = [myObject retain];
id obj = [myObject copy];
id obj = [myObject mutableCopy];
then you need to release it at some point -- in the same method, or your dealloc method, generally. In other words, balance your calls to alloc, retain, copy, and mutableCopy with a matching release call.
I remember reading somewhere that some objects come pre-retained, so I need to release them, but not retain them. Which objects are these?
This happens rarely. The documentation for the called method should specify that you are responsible for releasing the returned object; otherwise, you should assume you're receiving an autoreleased object.
if I alloc an object and only need it in that method, do I need to release it? retain it?
Yes, you need to release it (but you don't need to retain it). (You can also use one of the convenience methods that return an autoreleased object if you're only going to use it in that method.)
There is one and only one canonical reference: Apple's Memory Management Guide for Cocoa or iPhone.

Memory Management Autorelease vs. Alloc Question

3 correlated questions:
1.Do the code snippets below provide the very same results in terms of memory?
NSBundle *bundle=[[NSBundle alloc] init];
[bundle release];
bundle=nil;
and
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
NSBundle *bundle=[NSBundle mainBundle];
[pool drain];
pool=nil;
bundle=nil;
2.Why in
NSBundle *bundle=[[NSBundle alloc] init];
[bundle release];
the retainCount of bundle is 1, not 0?
3.Which is recommended: always use class methods, or always gain ownership by using alloc?
Thanks.
Yes, those should be equivalent in terms of memory management, from the developer's point of view. The frameworks might be doing something behind the scene to hang on to [NSBundle mainBundle], but that's not your concern.
Ignore retainCount. waves hand That's not the method you're looking for. Once you have relinquished ownership of an object, either by invoking release or autorelease, then it is invalid (bad practice) to send more messages to that object. In your example, you alloc an NSBundle, so you own it. That means it has a +1 retain count (I say +1, because it's relative). When you release the bundle, it now has a "0" retain count, which means you no longer own this object (despite whether or not it may still exist in memory), which means you should not send messages to it, under penalty of stuff blowing up in your face.
What's recommended is to use whatever's appropriate for the situation. If you just need a temporary object, then using a class method that returns an autoreleased object is probably going to be just fine. If you need to be absolutely sure that the object isn't going to go away while you're using it, then you can use an alloc/init approach (or retain an autoreleased object) and then just release it when you're done.
In the second example you will create 1 extra object (the NSAutorealeasePool) and because of that the two are not exactly the same in terms of memory. But after the code runs I believe the memory will return to the same state in both examples. I am not really sure but I believe that in the second example bundle is an autoreleased object, so when the pool is drained it gets released.
I believe that when the object gets dealloc'ed the retainCount isn't changed.
It is usually recommended to avoid class methods when you create a lot of temporary objects because they won't get released until the next AutoreleasePool drain is called (and if you don't have an AutoreleasePool inside your method it won't happen for sure until you return from your method - and maybe even later). Otherwise you should use the one that feels better for you. I personally prefer allocating them. It is also important to remember that if you want the autoreleased object (the one returned from a class method) to stick around even after you return from the function to retain it.