Using an object beyond Autorelease context - iphone

under the "Guaranteeing the Foundation Ownership Policy" in Apple developer's site article on Autorelease pool
http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html#//apple_ref/doc/uid/20000047-997594, they talk about extending an object's lifetime beyond the Autorelease pool.
Can someone give me a situation where this concept could be used?

Short answer: What the documentation is saying is that if you need to keep an object that has been autoreleased in an autorelease pool, you need to retain it.
Long answer: For instance, say I need to do a certain operation to 1000 objects. Once I'm done with these objects I'm going to autorelease them. Without an autorelease pool, they're going to be eventually released, but holding those 1000 objects in memory can make your program really slow (at least until they're autoreleased).
In order to solve this issue, I'm creating an autorelease pool that will be cleaned every 100 objects. However, what happens if I need to keep the last object of the last batch around? I still need to purge those other 99 objects. What I'm going to do is send a retain message to that very last object then clean the autorelease pool.
This way the autorelease pool will notify the system that it no longer wants those 100 items, but you've already let the system know that you do need one of them. If the object had a previous retain count of 1, then it'll still be around:
1 (original retain count) +1 (your retain) -1 (autorelease pool release) = 1.
This preserves the object after the autorelease pool is done with it.

Related

how objects values are retained when we drain the pool at the end of run loop

I know this sounds like a dumb question but I need to ask this. Well I read that autorelease pool is drained after one iteration of run loop after it has handled events. My question is that then how come my apps objects are retained after I clicked on button. So, by definition It should destroy all the objects which I have created (may be I have assigned some values to objects) after I click on button. But that doesnt happen ? right ? I can click my button again and again but I dont lose any object data.
Correct me if I am wrong somewhere.
You should watch a video or two from https://developer.apple.com/videos/ - Great introductions to memory management and such. And I also strongly recommend you look into ARC as soon as you grasp the basics of retain/release/autorelease.
All that the autorelease pool does is decrement the retain count of objects in the pool when it is drained. If that results in the retain count becoming zero, the object will be destroyed (dealloc'ed).
However, if an object has been retained more than once, the retain count will be greater than zero so it will not be destroyed (note that objects are created with a retain count of 1.)

calling -retain multiple times on the same object

What happens when you call -retain on an object many times? Is it OK to just release it once at when you're done using it?
consider the name "reference counting".
you must match each retain with a release (or autorelease).
when reference counting, your program may hold one or more references to an object. you add a reference by retaining the object. when you are done with the object, you forfeit the reference using release or autorelease. when all references are returned, the retain count reaches zero and the object is destroyed.
object lifetimes are also affected by autorelease pools; a convenience mechanism which reduces the number of manual retains/releases as well as reference counting complexity (in some cases). you should read up on autorelease and autorelease pools for a further understanding of this mechanism.
Always remember this three things.
1.) Whenever you pass a retain message to any object, its retain count increases by 1.
2.) And subsequently when you pass a release message to any object, its retain count decreases by 1.
3.) And whenever you are done with the object, always check that its retain count is 0.
Hence, the number of times you retain an object should always be equal to the number of times you release that object.
You can check apple documentation regarding memory management here.
How many times you call this method(retain) that many times Memory is allocated To that Object .you can Get Through Retain Count How many times Object Is being Allocated.
Its creates memory Issues.
If the Object Retain Count Is zero Then That Particular Object IS Not Unavailable to be used for other.
that to If your Retain 10times One Object if U release Once its not being released.
retain Increased by 1 count And Release Decreased by 1. if object having retain count 0 that object is unavailable.

Avoiding autoreleased objects, good practice or overkill?

I am just curious with regards to the following, when I am writing code I always try and manage the memory myself by sticking to non-autoreleased objects. I know that this means that objects are not hanging around in the pool, but I was just curious if doing it this way in general is good practice or simply overkill?
// User Managed Memory
NSSet *buttonSizes = [[NSSet alloc] initWithObjects:#"Go", #"Going", #"Gone", nil];
[barItemLeft setPossibleTitles:buttonSizes];
[barItemRight setPossibleTitles:buttonSizes];
[buttonSizes release];
.
// Autoreleased Memory
NSSet *buttonSizes = [NSSet setWithObjects:#"Go", #"Going", #"Gone", nil];
[barItemLeft setPossibleTitles:buttonSizes];
[barItemRight setPossibleTitles:buttonSizes];
Total overkill. If you read the relevant documentation carefully, it does not say that you should avoid autoreleasing objects. It says that you should avoid using autorelease pools when you in tight, object-rich loops. In those cases, you should be managing your memory explicitly (with retain and release) to ensure that objects are created and destroyed in an amortized manner.
The argument that the iPhone is a memory-constrained environment is true, but a complete red herring. Objective-C, with the Foundation and Cocoa frameworks (though they weren't called that at the time), ran just fine on a NeXTcube, which had 16MB of RAM (expandable to 64). Even the iPhone 3, which is pretty much EOL at this point, has 128MB.
edit
Since an iPhone app is a runloop-based application, a new autorelease pool is going to be created and destroyed every time it spins. This is clearly defined in the documentation. As such, the only reasons you'd have to create your own autorelease pool are:
Spawning a background thread, where you must create your own pool (since new threads, by default, do not have a base ARPool)
Performing some operation that will generate a significant number of autoreleased objects. In this case, creating and draining a pool would be to help ensure the limited lifetime of the temporary objects.
However, in the second case, you're recommended to explicitly manage memory as much as possible. This is so that your operation doesn't come to a screeching halt when it attempts to drain a pool with a few thousand objects in it. If you manage your memory manually, you can release these objects gradually as they are no longer needed, instead of saving them up for a single all-at-once release. You could help amortize the all-at-once release by nesting ARPools, which will help.
At the end of the day, though, just do what feels natural, and then (and only then) optimize it if you have concrete evidence that you need to do so.
edit #2
OK, it turns out that there is a recommendation to avoid using autorelease. BUT that recommendation is in the "Allocate Memory Wisely" section of the "Tuning for Performance and Responsiveness" area of the iOS Application Programming Guide. In other words, avoid it if you're measuring a performance problem. But seriously: autorelease has been around for ~20 years and did just fine on computers far slower and more constrained than the iDevices of today.
Unless you see performance issues (or memory issues), I wouldn't worry about using the autorelease pools. Furthermore, autorelease in theory can be more performant than non-auto release. The really dangerous places to use autorelease is in large loops (for example, when importing a large data set). In these cases you can run out of the limited iPhone memory.
I'd recommend you only focus on removing autorelease usage once you've finished your application and can identify memory management issues using the built in instruments.
When possible I like to use the autorelease methods. It eliminates the chance that I forget to release them or somebody comes in and changes the flow of the code so that the explicit release is bypassed. I vote that self-managing the releases is overkill.
It depends on whether or not an autorelease pool is in place. For instance, if you're using objective-c objects in an AudioUnit's render callback (which is called from a separate thread without an autorelease pool) your autoreleased objects will leak. In this case it's important that you release them manually, or wrap them in an autorelease pool.
In general though, I think it's up to you and your coding style
There's a balance. It depends a lot on the situation. In that particular case, assuming the barItem* variables are long-lived ivars, avoiding autorelease is pretty close to 100% pointless, because the set will be sticking around regardless of whether you release it now or two seconds from now.
In fact, in most cases, it makes little difference whether objects are released now or on the next iteration of the runloop, because the runloop is going so fast that it's actually capable of creating smooth animation. The iPhone is a particularly memory-starved platform, so it's good not to leave things alive too long. But at the same time, be realistic: One autoreleased NSNumber in a method that's called every couple of seconds isn't even going to make a dent in your app's profile. Even 100 thousand-character NSStrings will only use about 0.065% of the system RAM on an iPhone 3GS. That only becomes significant when you build up a ton of them in a very short time. So if there's no problem, don't sweat it.
I think there is only one resonable answer: usually autorelease is not an performance issue. It is good to keep in mind that it could be problematic in tight loops, but unless a performance meter like Instruments shows a memory spike you have to get rid of, I would use it if you like.
Premature optimization is a great way of spending time for nothing. Maybe in the end you know that your solution is elegant, but it could be that the easier solution performs just as fine.

Don't worry about `retainCount`? Really?

I've been told to not worry about retain counts. I understand that I shouldn't decide to release or retain using conditional logic based on retainCount, but should I not worry about it? I thought these correspond to memory usage in some way.
For instance, if I have a bunch of subviews of UIView that I've also put into an NSArray to be able to iterate through them, doesn't that double the retain count and therefore the memory use of the application? If so, is this costly or trivial, if the subviews are, say, 500 UIControl instances? This is assuming that I need the 500 instances, of course.
The value returned by retainCount is the absolute number of times the object has been retained. A UIView comes from a framework whose implementation is opaque. The implementation details aren't something you should worry about save for the documented interface you interact with.
And within that implementation, instances of UIView may be retained any number of times as a part of the implementation. In terms of memory, the actual number of retains is meaningless; 1 is the same as 5.
The only thing you should ever be concerned with is how your code changes an objects retain count.
If your code increases the retain count, it must decrease it somewhere or the object will stick around forever. If you retain, you must release (or autorelease). If you copy, you must release or autorelease. If you new or alloc, you must release (or autorelease).
That is it.
You're not supposed to be worrying about retainCount because it's often a misleading implementation detail of the reference counting system. What you're supposed to concern yourself with is following proper object ownership policy.
I post this once in a while from Apple's documentation:
Important: This method is typically of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.
As for your last question, your memory usage is not going to double from adding objects from one array to another array. The retain count is just an unsigned integer in the object that gets incremented by 1 when something claims ownership of it. But again, don't concern yourself with that.
For instance, if I have a bunch of subviews of UIView that I've also put into an NSArray to be able to iterate through them, doesn't that double the retain count...
Yes, it will.
... and therefore the memory use of the application?
No! The conclusion is wrong. 1000000 takes as much space as 0 when stored as a 32-bit integer.
The reason they say not to worry is that the retainCount field can often be very misleading. Aside from not knowing when the autorelease pool was last flushed or how many times an object has been autoreleased since, there are also some complicated internals, and system components could be temporarily holding references in ways that cannot be predicted. So if you start to study the retainCount you'll likely spend a lot time trying to figure out what other parts of the system are doing with various objects, which is not likely to help you get your application right.
You should design how your application works so that memory usage is not excessive.
You should worry about how many objects you have in memory, and how many times you have retained them (this is a number that will be less than the retainCount), and making sure you release them as many times as you retain them.
Calling retain on an object multiple times still only results in a single copy of the object being in memory.
To check for memory usage and/or leaks, you use the instruments leaks detector.
The retain count is just a number. An object whose retain count hits zero will get deallocated; aside from that, it doesn't matter if it's been retained once or fifty times.

Is this a memory management problem when using multiple threads?

Example: In my main thread (the thread that's just there without doing anything special) I call a selector to be performed in a background thread. So there's a new thread, right? And now, inside this background thread I create a new object which holds image data. Next I use that object and want to keep it around for a while. How would I store a reference to that object so I can release it later? Or will the thread be alive as long as this object exists? How does a thread relate to objects which were created in it?
Maybe someone can explain this in clear words :-)
Storage location and thread creation are two separate concepts. It doesn't matter which thread created an object in terms of who will finally 'own' it or when it will be released later.
Unfortunately, there's no clear-cut answer to your question, but I'd start by thinking about whether this object is a singleton, or whether it's a cache item that can be purged, or whether it's a result object that you need to pass back to some other selector asynchronously.
If it's a singleton, put it in a static var, and never release it (or, consider doing so in response to a low memory warning)
If it's a cache, then have the cache own the item when it's inserted, so you don't have to worry about it. You might need an autorelease to do this, but be careful when using autorelease and threads since each thread may have its own autorelease pool which gets drained at different times.
If it's an object that you need to pass back to another caller, you want to autorelease it as you return and let the caller pick up the ownership of the item.