I have experience with pure ARC coding. As a compiler feature it honors Objctive-C method family putting right retain/release calls whenever neeeded.
All methods that start with alloc, mutableCopy, copy and new create a new object. They increase the retain count. As a consequence, ARC will release any pointer (and hence the object associated with it) when I no longer need it.
I think that problems could arise when I write methods that do not follow naming conventions. For example, if I write a method like newCustomer that in a first version returns an autoreleased object while in a second version does not, what could happen?
In particular, my questions are the following (they belong to the same reasoning):
What happens if the calling and called code are both compiled with ARC?
(a) What happens if the calling code is compiled with ARC while the called is compiled with non-ARC?
(b) What happens if the calling code is compiled with non-ARC while the called is compiled with ARC?
It would be appreciated an answer that shows how ARC works under the hood (objc_release, objc_retainAutoreleasedReturnValue, etc.).
Thank you in advance.
A method named newCustomer would fall within the new method family and is thus implicitly marked as returning an retained object. When both calling and called code is compiled with ARC, then ARC balances the extra retain with a release in the caller:
When returning from such a function or method, ARC retains the value
at the point of evaluation of the return statement, before leaving all
local scopes.
When receiving a return result from such a function or method, ARC
releases the value at the end of the full-expression it is contained
within, subject to the usual optimizations for local values.
Source
If newCustomer is implemented with manual reference counting and violates the naming convention (i.e., does not return a retained object), then the caller can either over release or under release, depending on the circumstances.
If the caller uses ARC, then the object returned from newCustomer will be overreleased - likely causing the program to crash. This is because the calling code will participate in the second half of the above process, without having had a corresponding retain performed prior to that.
If the calling code is not compiled with ARC, but the called code is (thus correctly implementing returning a retained object), then the behavior depends on the programmer following the naming conventions. If they release the returned value, then the object's reference count will be correctly managed. However, if the programmer believes that their new... method does violate the naming convention, and fails to manually insert a release in the calling code, then the object that was returned will leak.
All in all, as Martin R. points out in the comments, the critical determination is whether the naming conventions are followed in any environment including manual reference counting.
Just like any other language, when you violate some of the basic assumptions of the language you wander into the area of undefined behavior. At some point in the future, Apple may modify the internals of how -new... does reference counting. It is up to Apple to make sure that code which conforms to the expected use works, but they won't do that for non-conforming uses.
If you need to know what the actual behavior is for a particular version of a compiler running on a particular system, then you must test for it. Don't assume that behavior will be the same for other compilers or versions of the runtime.
In the end, undefined behavior is undefined behavior. When you build code relying on it, you will eventually be affected by a subtle and difficult to diagnose defect.
Related
I have experience with pure ARC coding. As a compiler feature it honors Objctive-C method family putting right retain/release calls whenever neeeded.
All methods that start with alloc, mutableCopy, copy and new create a new object. They increase the retain count. As a consequence, ARC will release any pointer (and hence the object associated with it) when I no longer need it.
I think that problems could arise when I write methods that do not follow naming conventions. For example, if I write a method like newCustomer that in a first version returns an autoreleased object while in a second version does not, what could happen?
In particular, my questions are the following (they belong to the same reasoning):
What happens if the calling and called code are both compiled with ARC?
(a) What happens if the calling code is compiled with ARC while the called is compiled with non-ARC?
(b) What happens if the calling code is compiled with non-ARC while the called is compiled with ARC?
It would be appreciated an answer that shows how ARC works under the hood (objc_release, objc_retainAutoreleasedReturnValue, etc.).
Thank you in advance.
A method named newCustomer would fall within the new method family and is thus implicitly marked as returning an retained object. When both calling and called code is compiled with ARC, then ARC balances the extra retain with a release in the caller:
When returning from such a function or method, ARC retains the value
at the point of evaluation of the return statement, before leaving all
local scopes.
When receiving a return result from such a function or method, ARC
releases the value at the end of the full-expression it is contained
within, subject to the usual optimizations for local values.
Source
If newCustomer is implemented with manual reference counting and violates the naming convention (i.e., does not return a retained object), then the caller can either over release or under release, depending on the circumstances.
If the caller uses ARC, then the object returned from newCustomer will be overreleased - likely causing the program to crash. This is because the calling code will participate in the second half of the above process, without having had a corresponding retain performed prior to that.
If the calling code is not compiled with ARC, but the called code is (thus correctly implementing returning a retained object), then the behavior depends on the programmer following the naming conventions. If they release the returned value, then the object's reference count will be correctly managed. However, if the programmer believes that their new... method does violate the naming convention, and fails to manually insert a release in the calling code, then the object that was returned will leak.
All in all, as Martin R. points out in the comments, the critical determination is whether the naming conventions are followed in any environment including manual reference counting.
Just like any other language, when you violate some of the basic assumptions of the language you wander into the area of undefined behavior. At some point in the future, Apple may modify the internals of how -new... does reference counting. It is up to Apple to make sure that code which conforms to the expected use works, but they won't do that for non-conforming uses.
If you need to know what the actual behavior is for a particular version of a compiler running on a particular system, then you must test for it. Don't assume that behavior will be the same for other compilers or versions of the runtime.
In the end, undefined behavior is undefined behavior. When you build code relying on it, you will eventually be affected by a subtle and difficult to diagnose defect.
I have ARC code of the following form:
NSMutableData* someData = [NSMutableData dataWithLength:123];
...
CTRunGetGlyphs(run, CGRangeMake(0, 0), someData.mutableBytes);
...
const CGGlyph *glyphs = [someData mutableBytes];
...
...followed by code that reads memory from glyphs but does nothing with someData, which isn't referenced anymore. Note that CGGlyph is not an object type but an unsigned integer.
Do I have to worry that the memory in someData might get freed before I am done with glyphs (which is actually just pointing insidesomeData)?
All this code is WITHIN the same scope (i.e., a single selector), and glyphs and someData both fall out of scope at the same time.
PS In an earlier draft of this question I referred to 'garbage collection', which didn't really apply to my project. That's why some answers below give it equal treatment with what happens under ARC.
You are potentially in trouble whether you use GC or, as others have recommended instead, ARC. What you are dealing with is an internal pointer which is not considered an owning reference in either GC or ARC in general - unless the implementation has special-cased NSData. Without that owning reference either GC or ARC might remove the object. The problem you face is peculiar to internal pointers.
As you describe your situation the safest thing to do is to hang onto the real reference. You could do this by assigning the NSData reference to either an instance variable or a static (method local if you wish) variable and then assigning nil to that variable when you've done with the internal pointer. In the case of static be careful about concurrency!
In practice your code will probably work in both GC and ARC, probably more likely in ARC, but either could conceivably bite you especially as compilers change. For the cost of one variable declaration and one extra assignment you avoid the problem, cheap insurance.
[See this discussion as an example of short lifetime under ARC.]
Under actual, real garbage collection that code is potentially a problem. Objects may be released as soon as there is no longer any reference to them and the compiler may discard the reference at any time if you never use it again. For optimisation purposes scope is just a way of putting an upper limit on that sort of thing, not a way of dictating it absolutely.
You can use NSAllocateCollectable to attach lifecycle calculation to C primitive pointers, though it's messy and slightly convoluted.
Garbage collection was never implemented in iOS and is now deprecated on the Mac (as referenced at the very bottom of this FAQ), in both cases in favour of automatic reference counting (ARC). ARC adds retains and releases where it can see that they're implicitly needed. Sadly it can perform some neat tricks that weren't previously possible, such as retrieving objects from the autorelease pool if they've been used as return results. So that has the same net effect as the garbage collection approach — the object may be released at any point after the final reference to it vanishes.
A workaround would be to create a class like:
#interface PFDoNothing
+ (void)doNothingWith:(id)object;
#end
Which is implemented to do nothing. Post your autoreleased object to it after you've finished using the internal memory. Objective-C's dynamic dispatch means that it isn't safe for the compiler to optimise the call away — it has no way of knowing you (or the KVO mechanisms or whatever other actor) haven't done something like a method swizzle at runtime.
EDIT: NSData being a special case because it offers direct C-level access to object-held memory, it's not difficult to find explicit discussions of the GC situation at least. See this thread on Cocoabuilder for a pretty good one though the same caveat as above applies, i.e. garbage collection is deprecated and automatic reference counting acts differently.
The following is a generic answer that does not necessarily reflect Objective-C GC support. However, various GC implementaitons, including ref-counting, can be thought of in terms of Reachability, quirks aside.
In a GC language, an object is guaranteed to exist as long as it is Strongly-Reachable; the "roots" of these Strong-Reachability graphs can vary by language and executing environment. The exact meaning of "Strongly" also varies, but generally means that the edges are Strong-References. (In a manual ref-counting scenario each edge can be thought of as an unmatched "retain" from a given "owner".)
C# on the CLR/.NET is one such implementation where a variable can remain in scope and yet not function as a "root" for a reachability-graph. See the Systems.Timer.Timer class and look for GC.KeepAlive:
If the timer is declared in a long-running method, use KeepAlive to prevent garbage collection from occurring [on the timer object] before the method ends.
As of summer 2012, things are in the process of change for Apple objects that return inner pointers of non-object type. In the release notes for Mountain Lion, Apple says:
NS_RETURNS_INNER_POINTER
Methods which return pointers (other than Objective C object type)
have been decorated with the clang compiler attribute
objc_returns_inner_pointer (when compiling with clang) to prevent the
compiler from aggressively releasing the receiver expression of those
messages, which no longer appear to be referenced, while the returned
pointer may still be in use.
Inspection of the NSData.h header file shows that this also applies from iOS 6 onward.
Also note that NS_RETURNS_INNER_POINTER is defined as __attribute__((objc_returns_inner_pointer)) in the clang specification, which makes it such that
the object's lifetime will be extended until at least the earliest of:
the last use of the returned pointer, or any pointer derived from it,
in the calling function;
or the autorelease pool is restored to a
previous state.
Caveats:
If you're using anything older then Mountain Lion or iOS 6 you will still need to use any of the methods discussed here (e.g., __attribute__((objc_precise_lifetime))) when declaring your local NSData or NSMutableData objects.
Also, even with the newest compiler and Apple libraries, if you use older or third party libraries with objects that do not decorate their inner-pointer-returning methods with __attribute__((objc_returns_inner_pointer)) you will need to decorate your local variables declarations of such objects with __attribute__((objc_precise_lifetime)) or use one of the other methods discussed in the answers.
I am a experienced developer that is new to iOS developement (on iPhone in particular). A project I am working on is using Automatic Reference Counting (ARC).
I was doing some research on ARC and came across this document: http://clang.llvm.org/docs/AutomaticReferenceCounting.html and in a section titled: "Retained return values" it states that an attribute can be used to indicate that the caller expects to take ownership of a +1 retain count. It also goes on to state that ARC will automatically add the attribute to methods if it detects it is in particular method families (it specifically names: alloc, copy, init, mutableCopy, and new)
From further reading it seems that method families are simply method naming conventions. My understanding is that if the method name starts with a method family then it is in that method family. So for example
+(id) init
+(id) initWithName:(NSString*)name
are both part of the init method family.
My question is: Is there a formal list of defined Method Families for iOS development and if so, what are they / where might I find it?
below is the section llvm.org I mentioned above:
Section 3.2.2: Retained return values states:
A function or method which returns a retainable object pointer type
may be marked as returning a retained value, signifying that the
caller expects to take ownership of a +1 retain count. This is done by
adding the ns_returns_retained attribute to the function or method
declaration, like so:
id foo(void) __attribute((ns_returns_retained));
- (id) foo __attribute((ns_returns_retained)); This attribute is part of the type of the function or method.
When returning from such a function or method, ARC retains the value
at the point of evaluation of the return statement, before leaving all
local scopes.
When receiving a return result from such a function or method, ARC
releases the value at the end of the full-expression it is contained
within, subject to the usual optimizations for local values.
Rationale: this formalizes direct transfers of ownership from a callee
to a caller. The most common scenario this models is the retained
return from init, alloc, new, and copy methods, but there are other
cases in the frameworks. After optimization there are typically no
extra retains and releases required.
Methods in the alloc, copy, init, mutableCopy, and new families are
implicitly marked attribute((ns_returns_retained)). This may be
suppressed by explicitly marking the method
attribute((ns_returns_not_retained)).
It is undefined behavior if the method to which an Objective-C message
send statically resolves has different retain semantics on its result
from the method it dynamically resolves to. It is undefined behavior
if a block or function call is made through a static type with
different retain semantics on its result from the implementation of
the called block or function.
Rationale: Mismatches with returned results will cause over-retains or
over-releases, depending on the direction. Again, the rule about
function calls is really just an application of the existing C/C++
rule about calling functions through an incompatible function type.
Section 5 of the same document is titled "Method Families". It lists all the currently defined families, which are the ones you identified above; alloc, new, copy, mutableCopy, and init. It also lists the criteria for being part of that family. Mostly, it's just based on the method name, but it also depends on the return type. For example, a member of the copy family must return an object; a copy method that has a void return type will not be considered part of the copy method family.
I don't know that I've seen a formal list of method families, but your analysis is basically correct. I believe the only method naming conventions that have compiler-enforced semantics are those mentioned in your post, namely alloc, init, copy (and mutableCopy), and new. Even before/without ARC, the clang static analyzer included in Xcode uses those naming conventions to find memory management problems, and they're also the basis of the longstanding memory management rules for Objective-C programmers prior to ARC.
Namely, if you create an object using a method that begins with init, copy, mutableCopy or new, you "own" that object and are responsible for releasing it later. Objects created or returned by methods with any other name, are not owned by you, the caller, and if you want to keep a reference to them, you must retain them. Every retain you make must be balanced by a later release, when you're done with the object reference. Finally, calling autorelease on an object puts it in the innermost autorelease pool. The pool is responsible for releasing the object later, where later is sometime after the current scope. So, release and autorelease are both valid ways of relinquishing your retain on an object.
Now, the rules I've set forth shouldn't (and can't) be followed by you, the programmer, under ARC. However, ARC is essentially a system whereby the compiler with help from the static analyzer knows these rules and inserts the necessary memory management calls for you at compile time. So, if you're looking to develop an understanding of what ARC is doing behind-the-scenes, understanding these rules is a good start.
This turned out a bit longwinded, but the point is that the methods you've named are the only ones I know of that have this enforced naming convention in Objective-C, and it stems from the memory management rules set forth above. There are other naming conventions in Objective-C, to be sure, but they're standard style conventions, not something that's enforced anywhere.
Look at official Apple Developer documentation about Memory Management Rules. Seems, your list is complete: “alloc”, “new”, “copy”, or “mutableCopy” (only 4 keywords).
I would include the convenience constructors provided by some Cocoa classes:
- +stringWith* // Various ways to make NSString objects
- +arrayWith*, +dictionaryWith*, etc. // Make collections
- +dateWith* // Make NSDate objects
- etc. // Many, many others
They all return a new, autoreleased instance of the class they are sent to - except for some special cases, see for instance #Peter Hosey's comment.
I don't know if there are any formal rules, but the pattern is that the constructor name is composed of the class name without the NS part (and without the Mutable part, too, for mutable classes) followed by With<Parameter Type>: and one or more parameters. The name begins with a lower case letter (except the usual suspects, like URLWithString:.)
For instance, the following line provides an autoreleased NSArray instance with a single element:
[NSArray arrayWithObject: #"Test"]
I don't know if there are any special rules in the compiler to recognize this type of constructor.
How would you write a unit test—using OCUnit, for instance—to ensure that objects are being released/retained properly in Cocoa/Objective-C?
A naïve way to do this would be to check the value of retainCount, but of course you should never use retainCount. Can you simply check whether an object's reference is assigned a value of nil to indicate that it has been released? Also, what guarantees do you have about the timing at which objects are actually deallocated?
I'm hoping for a concise solution of only a few lines of code, as I will probably use this extensively. There may actually be two answers: one that uses the autorelease pool, and another that does not.
To clarify, I'm not looking for a way to comprehensively test every object that I create. It's impossible to unit test any behavior comprehensively, let alone memory management. At the very least, though, it would be nice to check the behavior of released objects for regression testing (and ensure that the same memory-related bug doesn't happen twice).
About the Answers
I accepted BJ Homer's answer because I found it to be the easiest, most concise way of accomplishing what I had in mind, given the caveat that the weak pointers provided with Automatic Reference Counting aren't available in production versions of XCode (prior to 4.2?) as of July 23rd, 2011. I was also impressed to learn that
ARC can be enabled on a per-file basis; it does not require that your
entire project use it. You could compile your unit tests with ARC and
leave your main project on manual retain-release, and this test would
still work.
That being said, for a far more detailed exploration of the potential issues involved with unit testing memory management in Objective-C, I highly recommend Peter Hosey's in-depth response.
Can you simply check whether an object's reference is assigned a value of nil to indicate that it has been released?
No, because sending a release message to an object and assigning nil to a variable are two different and unrelated things.
The closest you can get is that assigning anything to a strong/retaining or copying property, which translates to an accessor message, causes the previous value of the property to be released (which is done by the setter). Even so, watching the value of the property—using KVO, say—does not mean you will know when the object is released; most especially, when the owning object is deallocated, you will not get a notification when it sends release directly to the owned object. You will also get a warning message in your console (because the owning object died while you were observing it), and you do not want noisy warning messages from a unit test. Plus, you would have to specifically observe every property of every object to pull this off—miss one, and you may be missing a bug.
A release message to an object has no effect on any variables that point to that object. Neither does deallocation.
This changes slightly under ARC: Weak-referencing variables will be automatically assigned nil when the referenced object goes away. That doesn't help you much, though, because strongly-referencing variables, by definition, will not: If there's a strong reference to the object, the object won't (well, shouldn't) go away, because the strong reference will (should) keep it alive. An object dying before it should is one of the problems you're looking for, not something you'll want to use as a tool.
You could theoretically create a weak reference to every object you create, but you would have to refer to every object specifically, creating a variable for it manually in your code. As you can imagine, a tremendous pain and certain to miss objects.
Also, what guarantees do you have about the timing at which objects are actually released?
An object is released by sending it a release message, so the object is released when it receives that message.
Perhaps you meant “deallocated”. Releasing merely brings it closer to that point; an object can be released many times and still have a long life ahead of it if each release merely balanced out a previous retain.
An object is deallocated when it is released for the last time. This happens immediately. The infamous retainCount doesn't even go down to 0, as many a clever person who tried to write while ([obj retainCount] > 0) [obj release]; has found out.
There may actually be two answers: one that uses the autorelease pool, and another that does not.
A solution that uses the autorelease pool only works for objects that are autoreleased; by definition, objects not autoreleased do not go into the pool. It is entirely valid, and occasionally desirable, to never autorelease certain objects (particularly those you create many thousands of). Moreover, you can't look into the pool to see what's in it and what's not, or attempt to poke each object to see if it's dead.
How would you write a unit test—using OCUnit, for instance—to ensure that objects are being released/retained properly in Cocoa/Objective-C?
The best you could do is to set NSZombieEnabled to YES in setUp and restore its previous value in tearDown. This will catch over-releases/under-retains, but not leaks of any kind.
Even if you could write a unit test that thoroughly tests memory management, it would still be imperfect because it can only test the testable code—model objects and maybe certain controllers. You could still have leaks and crashes in your application caused by view code, nib-borne references and certain options (“Release When Closed” comes to mind), and so on.
There's no out-of-application test you can write that will ensure that your application is memory-bug-free.
That said, a test like you're imagining, if it were self-contained and automatic, would be pretty cool, even if it couldn't test everything. So I hope that I'm wrong and there is a way.
If you can use the newly-introduced Automatic Reference Counting (not yet available in production versions of Xcode, but documented here), then you could use weak pointers to test whether anything was over-retained.
- (void)testMemory {
__weak id testingPointer = nil;
id someObject = // some object with a 'foo' property
#autoreleasepool {
// Point the weak pointer to the thing we expect to be dealloc'd
// when we're done.
id theFoo = [someObject theFoo];
testingPointer = theFoo;
[someObject setTheFoo:somethingElse];
// At this point, we still have a reference to 'theFoo',
// so 'testingPointer' is still valid. We need to nil it out.
STAssertNotNil(testingPointer, #"This will never happen, since we're still holding it.")
theFoo = nil;
}
// Now the last strong reference to 'theFoo' should be gone, so 'testingPointer' will revert to nil
STAssertNil(testingPointer, #"Something didn't release %# when it should have", testingPointer);
}
Note that this works under ARC because of this change to the language semantics:
A retainable object pointer is either a null pointer or a pointer to a valid object.
Thus, the act of setting a pointer to nil is guaranteed to release the object it points to, and there's no way (under ARC) to release an object without removing a pointer to it.
One thing to note is that ARC can be enabled on a per-file basis; it does not require that your entire project use it. You could compile your unit tests with ARC and leave your main project on manual retain-release, and this test would still work.
The above does not detect over-releasing, but that's fairly easy to catch with NSZombieEnabled anyway.
If ARC is simply not an option, you may be able to do something similar with Mike Ash's MAZeroingWeakRef. I haven't used it much, but it seems to provide similar functionality to __weak pointers in a backwards-compatible way.
this is possibly not what you're looking for, but as a thought experiment I wondered if this might do something close to what you want: what if you created a mechanism to track the retain/release behavior for particular objects you wanted to test. Work it something like this:
create an override of NSObject dealloc
create a CFMutableSetRef and set up a custom retain/release functions to do nothing
make a unit test routine like registerForRRTracking: (id) object
make a unit test routine like clearRRTrackingReportingLeaks: (BOOL) report that will report any object in the set at that point in time.
call [tracker clearRRTrackignReportingLeaks: NO]; at the start of your unit test
call the register method in your unit test for every object you want to track and it'll be removed automatically on dealloc.
At the end of your test call the [tracker clearRRTrackingReportingLeaks: YES]; and it'll list all the objects that were not disposed of properly.
you could override NSObject alloc as well and just track everything but I imagine your set would get overly large (!!!).
Even better would be to put the CFMutableSetRef in a separate process and thus not have it impact your program runtime memory footprint overly much. Adds the complexity and runtime hit of inter-process communication though. Could use a private heap ( or zone - do those still exist?) to isolate it to a lesser degree.
As is common knowledge, calls to alloc/copy/retain in Objective-C imply ownership and need to be balanced by a call to autorelease/release. How do you succinctly describe where this should happen? The word "succinct" is key. I can usually use intuition to guide me, but would like an explicit principle in case intuition fails and that can be use in discussions.
Properties simplify the matter (the rule is auto-/release happens in -dealloc and setters), but sometimes properties aren't a viable option (e.g. not everyone uses ObjC 2.0).
Sometimes the release should be in the same block. Other times the alloc/copy/retain happens in one method, which has a corresponding method where the release should occur (e.g. -init and -dealloc). It's this pairing of methods (where a method may be paired with itself) that seems to be key, but how can that be put into words? Also, what cases does the method-pairing notion miss? It doesn't seem to cover where you release properties, as setters are self-paired and -dealloc releases objects that aren't alloc/copy/retained in -init.
It feels like the object model is involved with my difficulty. There doesn't seem to be an element of the model that I can attach retain/release pairing to. Methods transform objects from valid state to valid state and send messages to other objects. The only natural pairings I see are object creation/destruction and method enter/exit.
Background:
This question was inspired by: "NSMutableDictionary does not get added into NSMutableArray". The asker of that question was releasing objects, but in such a way that might cause memory leaks. The alloc/copy/retain calls were generally balanced by releases, but in such a way that could cause memory leaks. The class was a delegate; some members were created in a delegate method (-parser:didStartElement:...) and released in -dealloc rather than in the corresponding (-parser:didEndElement:...) method. In this instance, properties seemed a good solution, but the question still remained of how to handle releasing when properties weren't involved.
Properties simplify the matter (the rule is auto-/release happens in -dealloc and setters), but sometimes properties aren't a viable option (e.g. not everyone uses ObjC 2.0).
This is a misunderstanding of the history of properties. While properties are new, accessors have always been a key part of ObjC. Properties just made it easier to write accessors. If you always use accessors, and you should, than most of these questions go away.
Before we had properties, we used Xcode's built-in accessor-writer (in the Script>Code menu), or with useful tools like Accessorizer to simplify the job (Accessorizer still simplifies property code). Or we just typed a lot of getters and setters by hand.
The question isn't where it should happen, it's when.
Release or autorelease an object if you have created it with +alloc, +new or -copy, or if you have sent it a -retain message.
Send -release when you don't care if the object continues to exist. Send -autorelease if you want to return it from the method you're in, but you don't care what happens to it after that.
I wouldn't say that dealloc is where you would call autorelease. And unless your object, whatever it may be, is linked to the life of a class, it doesn't necessarily need to be kept around for a retain in dealloc.
Here are my rules of thumb. You may do things in other ways.
I use release if the life of the
object I am using is limited to the
routine I am in now. Thus the object
gets created and released in that
routine. This is also the preferred
way if I am creating a lot of objects
in a routine, such as in a loop, and
I might want to release each object
before the next one is created in the
loop.
If the object I created in a method
needs to be passed back to the
caller, but I assume that the use of
the object will be transient and
limited to this run of the runloop, I
use autorelease. Here, I am trying to mimic many of Apple's convenience routines. (Want a quick string to use for a short period? Here you go, don't worry about owning it and it will get disposed appropriately.)
If I believe the object is to be kept
on a semi-permanent basis (like
longer than this run of the runloop),
I use create/new/copy in my method
name so the caller knows that they
are the owner of the object and will
have to release the object.
Any objects that are created by a
class and kept as a property with
retain (whether through the property
declaration or not), I release those
in dealloc (or in viewDidUnload as
appropriate).
Try not to let all this memory management overwhelm you. It is a lot easier than it sounds, and looking at a bunch of Apple's samples, and writing your own (and suffering bugs) will make you understand it better.