Re: Issue with -[NSOutlineView autosaveExpandedItems] - SOLVED
Re: Issue with -[NSOutlineView autosaveExpandedItems] - SOLVED
- Subject: Re: Issue with -[NSOutlineView autosaveExpandedItems] - SOLVED
- From: Bill Cheeseman <email@hidden>
- Date: Sun, 13 Jul 2014 09:24:04 -0400
On Jul 12, 2014, at 5:57 PM, Ken Thomases <email@hidden> 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@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden