Controversy with ownership in Objective C - objective-c

During the last time I'm trying to become aware of Objective-C memory management and once I asked myself the following question:
Sinceweak reference in Objective-C let us to avoid retain cycles why not to use them all the time?

An object only stays in memory while there is at least one strong (default) reference to it. If you only use weak references, the object is immediately deallocated.
Simply said, "weak" means: This object belongs to someone else, I'm only accessing it and I don't mind if it disappears.

Sinceweak reference in Objective-C let us to avoid retain cycles why not to use them all the time?
Because an object is deallocated as soon as there are no strong references to it.
More importantly, a strong reference is often wanted in order to prevent an object's deallocation. For example, a view controller is ultimately responsible for its view -- it wouldn't make much sense to have the controller's view suddenly just disappear. So UIViewController's view property is strong.
A retain cycle happens when two objects each have strong references to the other. Neither object can be deallocated as long as the other one keeps it's strong reference. This isn't really a problem if you're aware of the situation, because you can break the retain cycle by eliminating either of the references. However, it's easy to not be aware of the cycle, or to forget to deal with it, and then you've got two objects keeping each other in memory beyond their useful lifetime. Making one of those references weak eliminates the problem, but it also means that the referenced object may be deallocated and the reference may become nil at any point. In practice, that's usually not a problem.

Related

Disadvantages of using weak variables even when not needed?

Seems Automatic Reference Counting (ARC) puts so much burden on the developer to keep track of references. Why couldn't you just make every variable weak and not have to worry about the strong retain cycles happening at all?
Im afraid you just dont understand ARC. ARC does the counting of references for you, depending on whether something is defined as strong or weak (in effect, strong increases the reference count, while weak does not). If a reference count becomes 0, it is removed from memory. So if everything was weak, properties would be removed from memory immediately, and you could not use them. You need a strong somewhere, in effect.
As a simple way to plan how to structure your strong / weak definitions, think of one particular class as the owner of a property, and give that one the strong. This means the property will stick around for that owner to use it. If another class also has a reference to that property, but does not require that the property always sticks around for it - make that weak. As long as the main owner class, say the View Controller, still exists - then so will the property. If both were set weak, then even though the property still appears, it will be empty, because at runtime, it was decided that no-one really needed it, and it was removed.
This is because you will need one strong reference as long as you need a reference to the object, as long as you need the referred object to survive in memory.
(You could go back to Objective-C where you can do all the works without ARC and do the memory management manually on your own. Apparently this could make you appreciate ARC.)
On the other hand you could ask the same question for strong references. The difference is that when you keep strong references only (no weak ones) then you don't have to think about weak or strong and it would work. (weak alone will most likely not work)
But then you would have to be 100% sure to null every strong reference to each object that you don't need anymore.
Side note:
When you add your object to a collection such as an array or a set (or as subview to a view) then these collection objects will keep strong references for you. In that case you don't have to care but to remove the object from that collection when the object can be discarded. This "trick" is only appropriate when you maintain these collections anyway - e.g. when it is about views that are part of the view hierarchy as long as they are required.
Under ARC object instance is alive as long as there is at least one strong reference to that object instance.
If you mark all variables as weak, there would be no strong references to object instance and nothing could keep it alive. It would be destroyed immediately upon creation.
If you are taking more than single reference to object instance you have to think about whether it should be marked as weak or strong (depending on particular code), there is no way around it.

Using an NSMutableArray of weak pointers

This is a purely theoretical question so please feel free to propose additional constraints or suggest alternative questions to discussion.
I know that in Objective-C almost any property that is mutable ought to be defined as (nonatomic, copy), but what if I want that property, say a mutable array, to be only just a list of weak pointers to objects already retained by some other class? For example, say I have a class called Concept and let's assume that all intended Concept instances have already been loaded and retained in memory somewhere by some class other than Concept. Say we add a nonatomic NSMutableArray property to each Concept instance called relatedConcepts that points to other Concept instances that are retained and already exist in memory.
What I know is that NSArrays are lists of strong referenced objects, but I want a list of weak referenced objects. How might I go about implementing this?
An NSArray ALWAYS keeps a strong reference to each of its items. This is by design as arrays are nil terminated and would become corrupted if one of the items ever became nil. The weak you are referring to would only apply to the array reference itself. Keeping "weak" items in an array is an advanced problem. My current solution involves using weak proxy objects which sounds kind of like what you were describing in your last paragraph. Whether you use copy or not isn't really relevant.
I have found some scenarios where keeping an array of weak references has come in handy. I've had to roll my own solution for that using weak proxies. Basically, you have an array of objects that then have a weak reference to the objects you actually care about. The weak proxy then needs to redirect all of the calls to it to the object it wraps.
You would use the strong specifier for your relatedConcepts property. That's to keep that instance from disappearing out from underneath you, regardless of the number or kind of references it contains.
There's no such thing as a mutable array that's a "list of weak pointers." NSMutableArray (as well as NSArray) maintains strong references to its members.
You're worrying far too much about what's retained (has a strong reference to it) and what isn't. That isn't your job. It's entirely possible that whatever is holding a strong reference to an object may choose to release it. Meanwhile, if nothing else is holding a strong reference to it, your weak reference falls to nil. Bad idea if you want to keep using it.

When do strong properties get released in ARC in iOS?

I have a quick question about ARC in iOS. (Sorry I've asked so many of these types of questions, but I'm just sooo confused regarding memory management.). It's important to note that I've never used the old memory maintenance system (retain, release, assign...etc) so I don't really know what those terms mean.
Right now I'm confused regarding what I have to do to make sure that strong properties get released properly. For example, suppose I'm making a school app and my School object contains strong property references to 5 different Child objects (not in an array). Each Child object has a strong pointer (property) to a Book object.
If I remove one of the Child objects from my school (say by making its property = nil, or by changing my property to point at a new object), will its Book be properly released? What do I have to do to make sure that this is the case? Do I need to write self.myBook = nil in a dealloc method? What if Child was a View Controller, would I need to write self.myBook = nil in the viewDidUnload method?
I'm targeting only iOS 5 (and up) so the old way of memory management doesn't really matter to me.
If I remove one of the Child objects from my school (say by making its property = nil, or by changing my property to point at a new object), will its Book be properly released?
Yes, it will be released as long as there are no other strong references to it.
What do I have to do to make sure that this is the case?
Nothing in particular: ARC will decrement object's reference count when you set the reference to that object to nil, see that the object is no longer referenced, and proceed to deleting it. It is smart enough to deal with the items referenced from the object being deleted, recursively, so you are not going to leak any memory.
One thing you have to worry about is circular references: if your Book has a strong back-reference to Child, either make that reference weak, or clear it out at the same time as you set your reference of Book to nil (the second option is error-prone, and therefore is not recommended).

Why are Objective-C delegates usually given the property assign instead of retain?

I'm surfing through the wonderful blog maintained by Scott Stevenson, and I'm trying to understand a fundamental Objective-C concept of assigning delegates the 'assign' property vs 'retain'. Note, the both are the same in a garbage collected environment. I'm mostly concerned with a non-GC based environment (eg: iPhone).
Directly from Scott's blog:
"The assign keyword will generate a setter which assigns the value to the instance variable directly, rather than copying or retaining it. This is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates."
What does it mean that you don't directly own the delegate object? I typically retain my delegates, because if I don't want them to go away into the abyss, retain will take care of that for me. I usually abstract UITableViewController away from its respective dataSource and delegate also. I also retain that particular object. I want to make sure it never goes away so my UITableView always has its delegate around.
Can someone further explain where/why I'm wrong, so I can understand this common paradigm in Objective-C 2.0 programming of using the assign property on delegates instead of retain?
Thanks!
The reason that you avoid retaining delegates is that you need to avoid a retain cycle:
A creates B
A sets itself as B's delegate
…
A is released by its owner
If B had retained A, A wouldn't be released, as B owns A, thus A's dealloc would never get called, causing both A and B to leak.
You shouldn't worry about A going away because it owns B and thus gets rid of it in dealloc.
Because the object sending the delegate messages does not own the delegate.
Many times, it's the other way around, as when a controller sets itself as the delegate of a view or window: the controller owns the view/window, so if the view/window owned its delegate, both objects would be owning each other. This, of course, is a retain cycle, similar to a leak with the same consequence (objects that should be dead remain alive).
Other times, the objects are peers: neither one owns the other, probably because they are both owned by the same third object.
Either way, the object with the delegate should not retain its delegate.
(There's at least one exception, by the way. I don't remember what it was, and I don't think there was a good reason for it.)
Addendum (added 2012-05-19): Under ARC, you should use weak instead of assign. Weak references get set to nil automatically when the object dies, eliminating the possibility that the delegating object will end up sending messages to the dead delegate.
If you're staying away from ARC for some reason, at least change assign properties that point to objects to unsafe_unretained, which make explicit that this is an unretained but non-zeroing reference to an object.
assign remains appropriate for non-object values under both ARC and MRC.
Note that when you have a delegate that's assign, it makes it very important to always set that delegate value to nil whenever the object is going to be deallocated - so an object should always be careful to nil out delegate references in dealloc if it has not done so elsewhere.
One of the reason behind that is to avoid retain cycles.
Just to avoid the scenario where A and B both object reference each other and none of them is released from memory.
Acutally assign is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates.

How do I find out if I need to retain or assign an property?

Are there any good rules to learn when I should use retain, and when assign?
Assign is for primitive values like BOOL, NSInteger or double. For objects use retain or copy, depending on if you want to keep a reference to the original object or make a copy of it.
The only common exception is weak references, where you want to keep a pointer to an object but can't retain it because of reference cycles. An example of this is the delegate pattern, where an object (for example a table view) keeps a pointer to its delegate. Since the delegate object retains the table view, having the table view retain the delegate would mean neither one will ever be released. A weak reference is used in this case instead. In this situation you would use assign when you create your property.
I would think that when working with objects you would almost always use retain instead of assign and when working with primitive types, structs, etc, you would use assign (since you can't retain non-objects). That's because you want the object with the property deciding when it is done with the object, not something else. Apple's Memory Management Guide states this:
There are times when you don’t want a
received object to be disposed of; for
example, you may need to cache the
object in an instance variable. In
this case, only you know when the
object is no longer needed, so you
need the power to ensure that the
object is not disposed of while you
are still using it. You do this with a
retain message, which stays the effect
of a pending autorelease (or preempts
a later release or autorelease
message). By retaining an object you
ensure that it won’t be deallocated
until you are done with it.
For discussion around using copy vs retain, see this SO question.
I know this was an old question, but I found these guidelines from the uber guru Matt Gallagher, super useful: http://cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html. In my case, I had a "retain hell" of my own making for having a hard reference to a parent object.
If you intend to keep the object and use it, use retain. Otherwise, it may be released and you'll end up with errors with your code.