Differentiate dead weak reference vs. nil value - objective-c

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.

Related

What does __weak do in this scenario

Class __weak *variable = preExistingObjectWithStrongReference;
If the above code is called, and a object with a strong reference is then pointed to by a new pointer 'variable', and the __weak attribute is assigned to it...
Does that simply mean that the reference count remains untouched? Or does it mean that the original object is now no longer strong referenced?
__weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong
references to the object.
This means that you can use variable safely as long as there's any other strong reference to the same object. In a certain sense you can think of it as the 'reference count remains untouched' as you said.
Neither; this means that the compiler will keep the reference alive as long as someone else points to it strongly. If there are no more strong references, and all of the objects that refer to your weak pointer are gone, the object is deallocated. Generally you only use weak on objects that you do not own. If you do own them (i.e it is something that "belongs" the the class) then strong is a better choice. A weak is essentially an unretained property, except the when the object is deallocated the weak pointer is automatically set to nil.

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.

Does an object has pointers to it's pointers?

In ARC, when an object is released, the pointer is set to nil.
How does the object tell all those points that it's about to be released?
Does this work for strong pointers or all types of pointers?
Based on some quick reading of what ARC required be added to the Objective-C runtime, the weak reference itself is registered with the runtime. There are a bunch of calls for setting up a weak connection, tearing it down and reassigning it. The compiler acts to decide what sort of assignment to do, much as it also has a role in automatically retaining and releasing. Per the linked document:
The runtime tracks __weak objects which holds non-null values. It is
undefined behavior to direct modify a __weak object which is being
tracked by the runtime except through an objc_storeWeak,
objc_destroyWeak, or objc_moveWeak call.
From that I'd conclude that the runtime maintains a collection of every weak pointer that currently points to a given object. When that object is deallocated it zeros out the pointers.
So there is a list, per object, that points to the relevant pointers to create a two-directional connection. How and where that's stored isn't explicit — it could be via the existing object association mechanisms, it could be a global dictionary, it could be just about anything.
In ARC (or MRC), a pointer is NOT set to nil when an object is released. In ARC, a weak object reference is set to nil when an object is deallocated, not when it is released. There is a big difference here.

ARC circular reference in objective-c uses delegate

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.

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.