Indeed, I believe that's my problem - currently when I add objects to my 
children array I do things such as [[myNode children] addObject:newNode], 
meaning I have nowhere to catch it. I'll update my code to add some accessors 
as you suggest, and change my - (NSMutableArray *)children accessor to - 
(NSArray *)children so that the compiler can catch any slips where I try to 
manipulate it directly. Regarding the weak reference to the parent, I guess I 
don't need to worry about that getting released because if it is, then so will 
the children be, or else by then they will refer to a different parent object.
Thank you!



________________________________
From: Mike Abdullah <[email protected]>
To: Keith Blount <[email protected]>
Cc: [email protected]
Sent: Tue, April 27, 2010 6:37:25 PM
Subject: Re: Fastest way to check for descendants of an object

Well that's pretty easy if you're writing proper accessor methods like:

- (NSArray *)children;
- (void)insertObject:(MyNode *)node inChildrenAtIndex:(NSUInteger)index;
- (void)removeObjectFromChildrenAtIndex:(NSUInteger)index;

Just call -setParent: or similar in the implementation.


On 27 Apr 2010, at 17:39, Keith Blount wrote:

Many thanks for the reply, much appreciated. That makes sense - the only (or 
rather difficulty) is ensuring the node always has an up-to-date reference to 
its parent given the number of scenarios in which it could change (for 
instance, if a node is copied etc).
>Thanks again,
>Keith
>
>
>
________________________________
From: Mike Abdullah <[email protected]>
>To: Keith Blount <[email protected]>
>Cc: [email protected]
>Sent: Tue, April 27, 2010 4:50:41 PM
>Subject: Re: Fastest way to check for descendants of an object
>
>Generally, you make MyNode also hold a weak reference to its parent node. (see 
>NSTreeNode/NSView for example)
>
>
>Then, when testing a node, can quickly recurse up the tree looking for a 
>desired ancestor.
>
>
>On 27 Apr 2010, at 16:33, Keith Blount wrote:
>
>Hello,
>>
>>I have a model object that represents a single node in a tree (it can be used 
>>in an NSOutlineView for instance). As such, it has a "children" 
>>NSMutableArray iVar which can store other objects of the same class, which in 
>>turn may have their own children.
>>
>>E.g:
>>
>>@interface MyNode : NSObject
>>{
>>  NSMutableArray *children;
>>}
>>@end
>>
>>Whereby "children" would contain instances of MyNode which in turn have 
>>"children" that may contain other instances of MyNode (obviously the above is 
>>just a grossly simplified version of my actual class which does much more).
>>
>>There are occasions when I need to check if one node object is the descendant 
>>of another node object. My current code for this is as follows:
>>
>>- (BOOL)isDescendantOfOrOneOfNodes:(NSArray*)nodes
>>{
>>   // Returns YES if we are contained anywhere inside the array passed in, 
>> including inside sub-nodes.
>>   NSEnumerator *enumerator = [nodes objectEnumerator];
>>   id node = nil;
>>   while (node = [enumerator nextObject])
>>   {
>>       if (node == self) return YES;  // Found ourself
>>       // Check all sub-nodes
>>       if ([[node children] count] > 0)
>>       {
>>           if([selfisDescendantOfOrOneOfNodes:[node children]])
>>               returnYES;
>>       }
>>   }
>>   // Didn't find self inside any of the nodes passed in
>>   returnNO;
>>}
>>
>>- (BOOL)isDescendantOfNodes:(NSArray*)nodes
>>{
>>   // Returns YES if any node in the array passed in is an ancestor of ours.
>>   NSEnumerator *enumerator = [nodes objectEnumerator];
>>   id node = nil;
>>   while (node = [enumerator nextObject])
>>   {
>>       // Note that the only difference between this and 
>> isAnywhereInsideChildrenOfNodes: is that we don't check
>>       // to see if we are actually one of the items in the array passed in, 
>> only if we are one of their descendants.
>>       // Check sub-nodes
>>       if ([[node children] count] > 0)
>>       {
>>           if([selfisDescendantOfOrOneOfNodes:[node children]])
>>               returnYES;
>>       }
>>   }
>>
>>   // Didn't find self inside any of the nodes passed in
>>   returnNO;
>>}
>>
>>So, in use, e.g:
>>
>>if ([firstNode isDescendantOfOneOfNodes:[NSArray arrayWithObject:secondNode]])
>>   // ... do something (e.g. prevent secondNode from being added as a child 
>> of firstNode).
>>
>>
>>My question is simply, is there a faster way of doing this? There are 
>>occasions when I need to run through and check potentially thousands of nodes 
>>each with thousands of descendants, and in this situation these checks can be 
>>quite time-consuming and slow things down. I know 10.5 introduced fast 
>>enumeration (e.g. "for (id node in nodes)"), and the only reason I'm not 
>>using that is that I need to support 10.4 too (I tested it and fast 
>>enumeration does speed things up a little, but not as much as I need at the 
>>volumes I'm talking about). So I'm just wondering if there is anything in the 
>>above that can be optimised to be faster. If not, I probably just need to 
>>re-examine where I'm calling these methods again, but I figured I'd start 
>>with first principles and initially check to see if there is any obvious 
>>quicker way of checking that an object is a descendant of another in the 
>>above situation that I might be missing.
>>
>>Thanks and all the best,
>>Keith
>>
>>
>>
>>_______________________________________________
>>
>>Cocoa-dev mailing list ([email protected])
>>
>>Please do not post admin requests or moderator comments to the list.
>>Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>>
>>Help/Unsubscribe/Update your Subscription:
>>http://lists.apple.com/mailman/options/cocoa-dev/cocoadev%40mikeabdullah.net
>>
>>This email sent to [email protected]
>>
>
>
>



      
_______________________________________________

Cocoa-dev mailing list ([email protected])

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to