I have a class, let's say Chicken, and I want a class-level method to enumerate all the currently existing Chickens. To do this, I keep a class-level NSMutableArray and add self to this in the init method.
This is great and my enumeration method simply returns a (non-mutable) pointer to this array.
The problem is that I can no longer deallocate a chicken by removing all pointers to it, as there is always a strong pointer left in the array.
E.g. If I do this...
Chicken *chick = [[Chicken alloc] init];
// Do something with the chick
chick = nil;
The chicken lives on because there is a strong pointer to it in the array. I could have a -[Chicken kill] method, which removes it from the array, but that's not neat.
What's the neatest way around this?
You can use [NSHashTable weakObjectsHashTable] to store objects. It is basically an array holds weak references. It is safe, and clean.
If NSHashTable is not available, or suitable (you want to hold key-value pair like NSDictionary) but you have ARC with __weak supported, you can use a wrapper object to hold weak reference.
I use block to hold weak ref in this example
NSMutableDictionary *globalDict = [NSMutableDictionary dictionary];
// put object
id obj = [Foo new];
__weak id weakRef = obj;
globalDict[key] = [^() { return weakRef; } copy];
// read object
id (^block)(void) = globalDict[key];
id obj = block ? block() : nil;
if (!obj) {
[globalDict removeObjectForKey:key];
}
Use + (NSValue *)valueWithNonretainedObject:(id)anObject values inside your array. To simplify your API, you can create a wrapping method of +arrayOfAllChickens which would iterate all non-retained values and add them to an array and return that.
Remember to remove the values from the array in dealloc or you could hit a bad access crash.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With