One solution to this kind of thing is to wrap your objects in a weak proxy object. Here is an example implementation of such an object:
https://github.com/j-h-a/jalib-core/blob/master/JALibCore/Helpers/JAWeakProxy.h
https://github.com/j-h-a/jalib-core/blob/master/JALibCore/Helpers/JAWeakProxy.m
Then you can do this:
NSMutableArray* a = [NSMutableArray array];
NSMutableArray* b = [NSMutableArray array];
[a addObject:[JAWeakProxy weakProxyWithTarget:b]];
[b addObject:[JAWeakProxy weakProxyWithTarget:a]];
Now both a
and b
are weakly referenced within the array. The good thing about using weak proxy objects is that you don't need to 'unbox' the real object inside them - you can just send messages (call methods) directly on the weak proxy object as if it were the target
and it will pass the message along. For example:
[a[0] addObject:@(0)];
Notice how a[0]
actually returns the weak proxy object holding b
as its target
, but I can sill send addObject
directly to this weak proxy representing b
(which is an NSMutableArray
) and the implementation of the weak proxy will ensure that the message is forwarded to b
.
However, you do lose some compile-time type-checking, so this technique is best used to help with the internal implementation of some class, which will have well-typed methods to access and enumerate the contents.
When I use such things I usually put in some auto-clean-up code into the array enumerators. That is I hide the arrays inside a utility class and provide block-based enumeration methods and I also keep a toRemove
array. When iterating I skip any objects that the target
has auto-zeroed to nil
and add them to the toRemove
array (the weak proxy object still exists even though its target
is gone), then afterwards I iterate through the toRemove
array and remove the proxy objects. You can also check if the target
is nil
and add it to the toRemove
array in any accessor helpers.