Thursday, April 22, 2010

Sight Words: Workflow and refactoring

Refactoring and extra functionality

Now that I have added the ability to merge words from multiple lists into my current list, I want the ability to merge words from my current list INTO other lists.   While doing this I'm also going to refractor the current functions so that the word selection stuff is in one place. 

In my previous code I had two routines specifically for the merge from lists functionality, I pull the common code out, and made two new routines that take parameters.  One routine that selects a set of words and then calls another function, and a second routine that selects a set of lists and calls a set of routines.  I also renamed the callback routines so that the workflow is explicit.

A case could be made for factoring this into a separate class, but I don't think it's necessary, all the context information is present in this class, and it's not a lot of code. 

Selecting lists

Note that I now take the label for the next action, and the function to be called as parameters.
- (void) doWordListSelection:(NSString*)nextAction nextFunction:(SEL) action
{
JLTableContainer *container=
[JLTableContainer createFetchControlledTable:nil 
  forEntity:@"WordList forSimpleKey:@"ListName" 
 inContext: [SightWordState Instance].control.managedObjectContext 
createSectionsBy:nil 
controlledBy:nil];
[container updatePredicate:nil];
UISelectionMaster * selector=[[UISelectionMaster alloc] init];
selector.listToSelect=container;
[self.navigationController pushViewController:selector animated:true];
[selector startSelection];
[selector showToolbar:nextAction target:self action:action];
self.listSelectDialog=selector;
}

Selecting words

- (void) doWordSelection:(NSString*)nextAction nextFunction:(SEL) action wordSet:(NSSet*) set
{
JLTableContainer *container=
[JLTableContainer createSetController:nil forList:set sortKey:@"wordName"
inContext:[SightWordState Instance].control.managedObjectContext
controlledBy:nil];
UISelectionMaster * selector=[[UISelectionMaster alloc] init];
selector.listToSelect=container;
[self.navigationController pushViewController:selector animated:true];
[selector startSelection];
self.wordSelectDialog=selector;
[selector showToolbar:nextAction target:self action:action];
}

The merge words from multiple lists into the current workflow

Note that I modified the names to violate standard coding standards a bit.  I want to make the purpose and workflow very clear.  I was loosing track of which routine was which, and this way it is explicit:

- (IBAction) copyFromLists1_selectLists:(id) sender
{
[self doWordListSelection:@"Select Lists" nextFunction:@selector(copyFromLists2_selectWords:)];
}
- (IBAction) copyFromLists2_selectWords:(id) sender
{
NSSet *selectedLists=[listSelectDialog currentSelectedItems];
NSMutableSet *words=[[NSMutableSet alloc]init];

for (WordList *list in selectedLists)
{
[words unionSet:list.containedWords];
}
[self doWordSelection:@"Add Words" nextFunction:@selector(copyFromLists3_doCopy:) wordSet:words];

}
// the final action.
- (IBAction) copyFromLists3_doCopy:(id) sender
{
[currentWordList addContainedWords:[wordSelectDialog currentSelectedItems]];
[self.navigationController popToViewController:self animated:true ];
self.wordSelectDialog=nil;
self.listSelectDialog=nil;
[[SightWordState Instance] save];
}
 
 

The merge words from the current list into multiple lists workflow

- (IBAction) mergeToLists1_selectWords:(id) sender
{
[self doWordSelection:@"Merge To Lists" nextFunction:@selector(mergeToLists2_selectLists:) wordSet:currentWordList.containedWords];
}

- (IBAction) mergeToLists2_selectLists:(id) sender
{
[self doWordListSelection:@"Do Merge" nextFunction:@selector(mergeToLists3_doMerge:)]; 
}
 
- (IBAction) mergeToLists3_doMerge:(id) sender
{
for (WordList *wordList in [listSelectDialog currentSelectedItems])
{
[wordList addContainedWords:[wordSelectDialog currentSelectedItems]]; 
}
[self.navigationController popToViewController:self animated:true ];
self.wordSelectDialog=nil;
self.listSelectDialog=nil;
[[SightWordState Instance] save];
}
A few things to note when renaming stuff, the : at the end of the selector is important, and the refactoring of the routines did not pick up the selectors when I did it.   It took a few debugging cycles to get it right.  Refactoring mostly fixed the nibs, but I had to do some reconnections to get everything working correctly.

No comments:

Post a Comment