On Jul 12, 2014, at 5:57 PM, Ken Thomases <[email protected]> wrote:
> You could do it this way:
> __block void (^__unsafe_unretained
> innerFindItemForIdentifierInArray)(NSArray *);
Thanks. I had gotten as far as thinking that I needed a second block variable
for the recursive call, but the proper placement of __unsafe_unretained didn't
come to me.
> This still has a problem. It doesn't stop when you intend it to. Any given
> -enumerate... call will stop if it directly finds the match, but an outer
> call won't. You could add "if (returnItem) *stop = YES;" after the recursive
> call. Or, you could pass the "stop" variable into the recursive call so that
> an inner call can set it.
Thank you for catching that! I was so focused on getting the block syntax right
that I completely overlooked the recursion issue.
Here's the final method. I should mention that my datasource is a property list
(hence my use of dictionaries). The root array does not have an identifier.
That's why I start right out with -enumerateObjectsUsingBlock:. I chose to use
blocks instead of recursive method calls partly to force myself to become more
familiar with block syntax, and partly because I understand that blocks
executing on the stack are likely to be faster. This method may have to
enumerate the datasource many times, depending on how many of the outline rows
are expanded.
- (id)outlineView:(NSOutlineView *)outlineView
itemForPersistentObject:(id)object {
// Datasource method per NSOutlineViewDataSource formal protocol. Required
if using autosaveExpandedItems. Called when application launches, once for each
item in the autosaved array in the user defaults preferences file. AppKit calls
this before -awakeFromNib, so the source list data source must be populated in
the designated initializer.
NSString *identifier = [NSKeyedUnarchiver unarchiveObjectWithData:object];
__block id returnItem = nil;
__block void (^__unsafe_unretained
innerFindItemForIdentifierInArray)(NSArray *);
__block void (^findItemForIdentifierInArray)(NSArray *) = ^(NSArray
*contents) {
[contents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL
*stop) {
if ([[obj objectForKey:ID_KEY] isEqualToString:identifier]) {
returnItem = obj;
*stop = YES;
}
id subarray = [obj objectForKey:CONTENTS_KEY];
if (subarray) {
innerFindItemForIdentifierInArray(subarray); // recursive
if (returnItem) {
*stop = YES;
}
}
}];
};
innerFindItemForIdentifierInArray = findItemForIdentifierInArray;
findItemForIdentifierInArray([self sourceListContents]);
return returnItem;
}
--
Bill Cheeseman - [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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]