Changing auto-released object to non-auto - objective-c

Is there a way to change an autoreleased object to one that is non-autoreleased?
NSCoder's decodeObjectForKey returns an autoreleased object, which messes with a couple memory systems in my app. How can I change its returned value to a non-autoreleased object?
I know I can run retain on it, but if I release it, it'll still remain autoreleased. Whereas, I want to manage the memory myself.

Set up an autorelease pool before you retrieve the autoreleased object. It will be in that autorelease pool. Retain the object. Now release the autorelease pool. Your object is no longer in an autorelease pool. It's retained, and it's now your responsibility to release it.

Related

ARC and memory management

I'm still not 100% with ARC internals.
A few examples that I would like clarified:
What happens with someObjectToReturn = [[SomeClass alloc] init]; that is allocated inside a method and returned? If someObjectToReturnis assigned to e.g. someObject, when will someObjectToReturn be released? When someObject is nilled or does someObjectToReturn still need to be added to an autorelease pool?
Another case is if an array of objects is nilled, are all the objects released?
Lastly, where is a good place to release a copied block object? Or will the block still be released after execution? If the copied block is added to an autorelease pool, when would one drain that pool?
Lets say there are 10 blocks, each added to an autorelease pool, draining it too soon would result in the executing blocks to die. Can a copied block be nilled from within itself, such as dispatching the nilling of the block back to the main thread?
You seem to be overcomplicating things. Under ARC, you can't release objects, or drain autorelease pools, so there is no "right" time to do this. Don't think about retain and release and autorelease (except in tight loops), think about object ownership.
Your specific questions:
The object will be released when the variable that the return value is assigned to goes out of scope or is set to nil. You don't have to worry about it.
Yes, all the contents of an array are released when the array is set to nil, you don't have to worry about it
You can set the value holding the copied block to nil when you're done, or it will disappear when the object owning the copied block goes. You can't drain an autorelease pool under ARC, you can wrap statements in an #autoreleasepool{} block, but this just captures everything in the block - you don't "add" things to the pool or "drain" the pool.

What happens if your mark an autorelease object as autorelease

My question may sound stupid an all, but I like to know what happens if I mark an autoreleased object as autorelease. Will it be released twice? Or nothing happens? For example:
Obj * obj = [[Obj create] autorelease];
Let's say [Obj create] returns an autoreleased object.
If I add another autorelease, what happens then?
Yes, sending autorelease twice will release the object twice. If your create method returns an autoreleased object and you send another autorelease message to it, your app will crash, because you'll be releasing a deallocated object.
Having said that, why don't you use the new Automatic Reference Counting (ARC)? You don't have to worry about (auto)releasing objects anymore.
You use the Class Method(+), you should not to care the memory. People use Class Method one reason is that it can return an autorelease object. If you release or autorelease the object which the Class Method returns, it will crash.

How is a thread related to its NSAutorelease pool?

I have a general idea on how NSAutorelease pool works.
we have objects in it which are autoreleased and when the drain method is called.
the pool is checked for objects with retaincount as +1, and are thus deallocated.
but what I am not sure of is.
We create object of NSAutoRelease pool in the main thread as well as one for each thread.
How is a thread related to that particular pool.
What happens if we create two or more autorelease pools in one thread.
we just create the pool object and drain it when our work is done.
its not like that we get a singleton or something .
Then how does the thread get to that particular pool ?
Explanation of the scenario of what I mean by retain count 1. [slightly incorrect, read the edit]
Obj A has a method createAndReturn.
createAndReturn creates an object autorel_obj and returns it.
Now it can't just release it as it has to return it.
So it will autorelease it and return.
Thus autorel_obj will be in autorelease pool.
now say objB calls createAndReturn of ObjA.
and gets hold of autorel_obj and retains it otherwise autorelease pool will drain it.
Now when it is being retained by objB, its retain-count is 2.
[Here is the incorrect part corrected in, the EDIT]
Autorelease pool just cant release autorel_obj until it is also being used by objB also.
thats why until objB also releases it and its retain count becomes '1', it cant be released.
so By retainCount 1, what I mean is that the object which sent it to the pool is the only one owning it.
and regarding pool and thread relation, Firoze Lafeer answer was helpful.
EDIT to retain count 1 scenario:
As correctly pointed out by Firoze,
My earlier explanation of retain count 1 needs a change.
autorel_obj will only be released when pool is drained and hence its retain count will go down by 1.
It wont be deallocated from memory.
Once every other owner obj of autorel_obj releases it and its retain count becomes 0.
then only it is deallocated from the memory.
Sorry for all the trouble, Thanks to Firoze for the correction.
the pool is checked for objects with retaincount as +1, and are thus deallocated.
I'm not sure I understand that statement completely, but it sounds incorrect to me. There is nothing conditional about autorelease. If you autorelease an object, it will be released when the pool is drained, regardless of its retain count at that point (even if the object had already been deallocated!) It's better to think of "autorelease" as "deferred release".
As for the other question, each thread maintains its own stack of autorelease pools. Each pool is associated with one (and only one) thread.
Which thread is a given pool associated with? The answer is whichever thread created the pool. If you create a new pool where one exists already, then the new pool is "nested" within the existing pool. Objects autoreleased within the scope of that new pool will be released when that pool is drained (when the scope of that pool ends).
I hope that helps?
EDIT
To address your edit:
Your explanation is not correct. The autorelease pool can and does release the object as soon as it is drained. It doesn't wait for objB to release it first. It doesn't even know what other objects may have retained autorel_obj from your example. I think you're confusing release with deallocation.
So the scenario is this:
createAndReturn allocates and autoreleases autorel_obj (retain count is +1)
objB retains autorel_obj (retain count +2)
pool is drained, autorel_obj is released by the pool (retain count +1)
at some point in the future, objB releases autorel_obj (retain count 0)
autorel_obj is deallocated
So, again, the pool doesn't know and doesn't care what other objects may have retained the object it is releasing. It does the release, unconditionally, when drained. That may not cause the object to be deallocated immediately, but that's not the pool's concern.

Objective C - Memory Management and autorelease ???

Does autorelease guaranty that at the end of blocks the object will get released?
Or is it better to manually release objects?
It guarantees it will be released sometime after the block executes, not necessarily immediately after. It's up to the runtime to determine exactly when.
It's not big deal unless you're doing something with a lot of autoreleased variables, like creating them in a big loop, or if you're creating large autoreleased objects, like UIImages. In these cases, you should manually release when you're through, otherwise autorelease is perfectly acceptable.
If an object is autoreleased, you MUST not manually release it (unless it is retained of course). The NSAutoRelease pool which is part of the UIKit event handler will release it for you. If you were to manually release the object, the pool may cause a crash or other undefined behavior as the object will be doubly-released.
If there are cases where you generate a lot of objects or use a lot of memory in objects, you can pre-emptively autorelease them (perhaps in your loop) by creating your own NSAutoReleasePool - pools can be nested.
It's better to release objects rather than autorelease, unless of course you have an explicit reason to use autorelease, for example use autorelease when returning an object the method retained and you can't avoid it.
Basically autorelease should be used as an excuse to completely avoid memory management. You want to release objects as soon as you possible can. Autorelease just says the object will be released some time in the future.

Can I early-release an autorelease object?

i.e. would cause the object to be released immediately and not have to be released by the pool if I did this?
[[NSArray arrayWithCapacity:100] release];
Can't find a clear explanation in the docs about this.
It would likely crash when the object would normally be autoreleased. autorelease means "delayed release", so it will be released: just later. Since the object won't exist later as you are manually releasing it, you will likely crash due to the runtime sending the -release message to your now-deallocated object.
Edit: Note that if you -retain objects that come autoreleased, you do have to -release them: you are taking ownership.
I realise that this is stupid now, and that I shouldn't be releasing something I don't own.
If you don't want the object to go into the auto-release pool, you can do a manual alloc and initWithCapabity. If you do that, you'll have to manually release it at some point.