Jimmy
Jimmy

Reputation: 1104

How to avoid retain cycle when dealing with NSArray(Which retains object by default )?

My situation is that I have two Classes : "Person" and "Group". In every person, it has a NSArray that restores every group it belong to. In every group , it has a NSAraay that restores every person belongs to it.

And one person can belong to many group and one group can have many people belongs to it.

And This is a kind of retain count I think,A person retains a NSArray which retains the Group Which retains a NSArray which retains back to the person.

But I think I do need every person knows which group it belongs to and every group knows the persons belongs to it.

How can I solve this?

I think it the NSArray doesn't retains all it's members that would break the cycle but obviously NSArray must retains them.So please provide some advice.

Upvotes: 2

Views: 454

Answers (3)

Akshay
Akshay

Reputation: 5765

It seems after reading the question that you need to persist this data across app launches (I might be completely wrong). If this is true, you should have a look at CoreData & create database entities for Person & Group. In that case, CoreData will manage all your references & you can fetch 'persons in a group' & 'groups of a person' using SQL like queries.

If this is not true, a simple solution that comes to my mind is to store indirect references rather than direct references. For example, each person or group shall have an ID (let's say it is an NSString). Then, each Person class will store an array of NSStrings (group IDs corresponding to groups to which it belongs) & each Group class will store an array of NSStrings (person IDs corresponding to its members). With this, you will need to maintain a Map/Dictionary structure which stores pairs like <personOrGroupID, PersonOrGroupObject> & look up the IDs in this structure.

Upvotes: 0

Christopher A
Christopher A

Reputation: 2961

In general, you would need a weak referencing system to achieve this. You can use a non-retaining CFArray, but bypassing the retain/release system is dangerous. Here is a quick-and-dirty category on NSMutableArray to allow for this.

@implementation NSMutableArray (WeakReferences)
    + (id)mutableArrayUsingWeakReferences {
    return [self mutableArrayUsingWeakReferencesWithCapacity:0];
    }

    + (id)mutableArrayUsingWeakReferencesWithCapacity:(NSUInteger)capacity {
    CFArrayCallBacks callbacks = {0, NULL, NULL, CFCopyDescription, CFEqual};
    // We create a weak reference array
    return (id)(CFArrayCreateMutable(0, capacity, &callbacks));
    }
@end

For your specific case, I would take a step back and see if there isn't a better way to structure your classes to circumvent this problem entirely.

Upvotes: 0

jtbandes
jtbandes

Reputation: 118651

You can use [NSValue valueWithNonretainedObject:...] to put your objects into an array without retaining them. I'm not sure if this is the best solution, but it will work.

Upvotes: 2

Related Questions