I've got an NSOutlineView
that shows TrainingGroup entities.
Each TrainingGroup represents a folder on the local machine.
The NSOutlineView
is bound to an NSTreeController
with a fetch predicate of IsTrained == 0
Each TrainingGroup can be assigned to a project.
Each TrainingGroup has many TrainingEntries that show a time worked on that file.
When the TrainingGroup is assigned to a project, the IsTrained
is set to YES
.
On assign to a project, all descendants are also assigned to that project and their IsTrained
property is set to YES
too.
Project column is bound to projectTopLevel
property.
Example
The whole tree looks like this:
Name Project IsTrained
Users nil NO
John nil NO
Documents nil NO
Acme Project Acme Project YES
Proposal.doc Acme Project YES
12:32-12:33 Acme Project YES
13:11-13:33 Acme Project YES
... etc
Budget.xls Acme Project YES
Big Co Project Big Co Project YES
Deadlines.txt Big Co Project YES
Spec.doc Big Co Project YES
New Project nil NO
StartingUp.doc nil NO
Personal Stuff Personal YES
MyTreehouse.doc Personal YES
Movies nil NO
Aliens.mov nil NO
StepMom.mov nil NO
And the NSOutlineView would only see this:
Users nil NO
John nil NO
Documents nil NO
New Project nil NO
StartingUp.doc nil NO
Movies nil NO
Aliens.mov nil NO
StepMom.mov nil NO
If you assigned Movies to Personal, the view would now look like this:
Users nil NO
John nil NO
Documents nil NO
New Project nil NO
StartingUp.doc nil NO
Code
TrainingGroup.m
-(void)setProjectTopLevel:(JGProject *)projectToAssign {
[self setProjectForSelf:projectToAssign];
[self setProjectForChildren:projectToAssign];
}
-(void)setProjectForSelf:(JGProject *)projectToAssign {
[self setProject:projectToAssign];
}
-(void)setProjectForChildren:(JGProject *)projectToAssign {
for (TrainingGroup *thisTrainingGroup in [self descendants]) {
[thisTrainingGroup setProject:projectToAssign];
if(projectToAssign != nil) {
[thisTrainingGroup setIsTrainedValue:YES];
} else {
[thisTrainingGroup setIsTrainedValue:NO];
}
// Other code updating rules.
}
}
-(JGProject *)projectTopLevel {
return [self project];
}
-(NSSet *)untrainedChildren {
// Code that loops through all children returning those
// whose isTrained is NO. Omitted for brevity.
}
As you can see above, I'm running all the project assignment code on the main thread currently.
When there are hundreds of time entries under each folder, my app becomes unresponsive.
1 Modal progress bar
The Approach
The Good
The Bad
2 Non Modal Spinner
The Approach
The Good
The Bad
3 Hide
The Approach
Good and Bad
4 Improve performance
The Approach
The Good
The Bad
As far as I can see, none of the options above are ideal.
1. Which is the best option?
2. Are there any other options?
3. What could I improve about my approach?