ARC circular reference in objective-c uses delegate - objective-c

Hello!
I tried to use a delegate in my app. My project uses ARC
For example, I have protocol X and two object which uses it.
In object B I created an instance for object A and set delegate self (A.delegate = self)
In runtime I invoke a method callBack (in this point my delegate object is B). After that they all execute the -showResult method.
At what point is a circular reference formed? I understand that this is a problem with the specifier strong, but I don't understand what time it happened, and how to track it.
Thanks!

If two objects both maintain strong references to each other (that is, they retain each other), you may have what's known as a 'retain cycle' on your hands. Neither object will ever be deallocated because the other has a strong reference to it (retains it), and so it will never give up its reference (release) the other object.
This situation is common with delegates, where one object (call it A) creates another (B) and sets itself as B's delegate. If A has a strong reference to B so that B won't get deallocated, and B also has a strong reference to A, you have a reference cycle. In order to avoid that, it's common for objects not to retain or keep strong references to their delegates. Make B's reference to A weak instead of strong and the problem goes away.

It looks like you keep a strong reference to A in B. Either make it a weak reference or - which is the common practice - make the delegate a weak reference. In the latter case you should make sure to set A's delegate to nil before B is deallocated.

Related

Differentiate dead weak reference vs. nil value

As far as I know, when I dereference a dead weak reference in Objective-C, I get a nil value as the result. I'm wondering if there is any way to actually tell if there was a weak value assigned to the variable once it goes away as opposed to simply having a value of nil (for instance if the reference was never assigned).
Is there perhaps a lower-level runtime function that I can use?
I've taken to using a BOOL to record when the reference is assigned, but this feels ugly to me.
As Rob said, you can't do it directly. But you can do so indirectly.
By using associated objects, you can associate a subclass of NSObject with the object being weakly referenced. In that subclass, override dealloc to notify something that the weakly referenced object is being deallocated.
As long as you make absolutely sure that the weakly referenced object's associated reference to your NSObject subclass is the only strong reference to your subclass's instance, then you've effectively created a means of receiving a notification of when the weakly referenced object is deallocated.
Yes, it is fragile. One additional strong reference to that subclass's instances and the whole thing stops working.
No, there is no way to tell if a weak reference has been set to nil because its referent has been deallocated.
The weak reference is set to nil by weak_clear_no_lock in objc-weak.mm.

object still exists after setting to nil

I am using ARC. I have a method that runs at the end of a game I have written which should clear up memory. There are a series of objects in an NSMutableArray, which i remove using removeObject:. I then set these objects to nil. However, using NSLog on these objects shows that they still exist. Why does setting them to nil not remove them from memory?
In ARC (automatic reference counting), setting a reference to an object to nil means two different things depending on the kind of reference you are nil-ing:
If it is a strong reference, then nil-ing it means decreasing the reference count of the referenced object;
if it is a weak reference, nil-ing it does nothing.
Thus, nil-ing can lead to different outcomes. Specifically, it is only when the reference count goes to zero that the object is deallocated. This would correspond to a case where no other object in the system is owning the first one (which means holding a strong reference to it).
So, in your case there could be either some other objects keeping a strong reference to the objects you try to nil; or, you might be nil-ing a weak reference. If you show some code, it may become clearer.

Is it better practice to make member vars retained versus assign

I have member variables in my custom UIViewController that are defined as 'assign' (not 'retain') like this:
#property (nonatomic, assign) UIButton* mSkipButton;
In my loadView method, I set the var, for instance self.mSkipButton, to an autoreleased alloc of the variable type. I then attach it to my controller's view essentially having the view reference count and release it as needed.
This concerns me, however, that I have the pointer stored in my member var and that it could be referencing released memory if the count decrements at some point. Is it better practice to instead declare the variable as 'retain' and then in the viewDidUnload method release the member var (or just set it to nil to release and make sure i don't have an address in there)?
Alternatively, could I simply set the member var to nil in viewDidUnload and not make it a retained variable?
Is it better practice to instead declare the variable as 'retain' and then in the viewDidUnload...?
Yes, use retain -- good instinct. In viewDidUnload, you'd typically just set it to nil via the ivar's setter: self.ivar = nil;
I find it easier to be aware of and manage object codependencies explicitly, than to deal with issues related to using assign. You can completely avoid the issues of holding an unmanaged reference.
Arguments can be made that assign would usually be fine here (and it is in some cases), but using assign can complicate object graphs and ownership for anyone working with the class. As program complexity grows (and the libraries you depend on change), it becomes increasingly difficult to track lifetimes of unmanaged references. Things tend to break, or operate differently on different hardware and software combinations. Attempting to manage the lifetime of an unmanaged object over a complex program or in a concurrent context is self abuse. Guaranteeing defined and predictable behavior/operation reduces bug counts.
That's a property, not a "member var" (known in Objective-C as an instance variable or ivar.)
The semantics of a property depend on how that property is going to be used. Generally speaking, you'll want your properties to be retained for the lifetime of your object. If the property is a connected IBOutlet, this will be done for you by the NIB loader; otherwise, you must be explicit and use the retain or copy attribute on the property.
For objects that are expected to own your object, a property should always be marked assign to avoid a retain loop. For example, an object usually owns any object for which it acts as a delegate (usually, but not always--every CS rule has an exception.)

Can I just release the top object (iPhone)?

If I release the object that's holding a reference to the variable that I need to release, is that sufficient? Or must I release at every level of the containment hierarchy? I fear that my logic comes from working with a garbage collector for too long.
For instance, I assigned to this property of a UIPickerView instance by hand instead of using IB
#property(nonatomic, assign) id<UIPickerViewDelegate> delegate
Since it's an assign property, I can't just release the reference after I assign it. When I finally release my UIPickerView instance, do I need to do this:
[singlePicker.delegate release];
[singlePicker release];
or is the second line sufficient?
Also: Are these assign properties the norm, or is that mostly for Interface Builder? I thought that retain properties were the normal thing to expect.
The properties are declared assign instead of retain for a reason - delegates are not owned by their holders and they don't call release on them. Otherwise there would be a problem with circular references. You however have to call release on the object you use as the delegate somewhere if you own them.
If delegates were retained, imagine the following situation:
a takes b as a delegate, retains b
b takes a as a delegate, retains a
Now you have a circular reference - without ugly cleanup code that explicitly tells them to release their delegates, both of the objects will never be deallocated.
The subject is treated in Delegation and the Cocoa Application Frameworks:
Delegating objects do not (and should not) retain their delegates. However, clients of delegating objects (applications, usually) are responsible for ensuring that their delegates are around to receive delegation messages. To do this, they may have to retain the delegate in memory-managed code. This precaution applies equally to data sources, notification observers, and targets of action messages. Note that in a garbage-collection environment, the reference to the delegate is strong because the retain-cycle problem does not apply.

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.