The next form is the core of managing my lists. It dispays the name of the list and the category and allows direct editing of these features. Categories are intended to be use for filtering and sorting so that a larger number of lists can be used.
Next a series of large friendly buttons allow transfer to other areas:
Edit list
This brings up the current contents of the list the user can then delete words in bulk or add new words.
Merge from other lists
This will allow the user to select one or more other lists. After selecting these lists a dialog will be brought up showing the combined set of words in those lists. The user can then select which words they want. Select and clear all will be available.
Merge to list
This will bring up a dialog that allows the user to select words to merge. Once done a dialog will be brought up allowing the user to select lists to send these words to.
A common factor in these dialogs is the selection of lists. The core feature of this application vs other sight word applications is intended to be the easy manipulation of lists.
Below is the initial cut of the dialog. After I get the application working I intend to do an 'aesthetic' run-through to add landscape capability and to make it look prettier. This is the primary reason I didn't do this as a table, I think it is easier to implement as a standard dialog, and it offers more freedom to make modifications.
Now this screenshot isn't the most attractive dialog, but it includes the essential information.
I do intend to clean it up prior to release, and to also make another .nib file that contains a landscape version of the dialog.
I also refactored the sight word display, since I am having it initiated from two locations, I made a static method on the SightWordDisplay class that shows the dialog. I also intend to clean up this some more, I'm not satisfied with my 'singleton' sight word state.
Showing posts with label flash cards. Show all posts
Showing posts with label flash cards. Show all posts
Friday, March 26, 2010
Wednesday, March 24, 2010
Refactoring Suggested Items: The template
The container template
The first template is a small set of code that has some utility routines to create two types of tables, and which contains the other strategies. It is currently a little clunky, a future refactoring will try to make the API cleaner
The header file
/
// JLTableContainer.h
// JLFoundation
//
// Created by Jon Lundy on 3/20/10.
//
#import
#import
@interface JLTableContainer : NSObject
{
NSObject<JLCallbackHandler> *callbackHandler;
NSObject<JLTableSource> *tableSource;
NSObject<JLCellProvider> *cellProvider;
NSObject<JLTableController> *tableController;
UITableView *table;
}
@property (retain,nonatomic) NSObject *callbackHandler;
@property (retain,nonatomic) NSObject *tableSource;
@property (retain,nonatomic) NSObject *cellProvider;
@property (retain,nonatomic) NSObject *tableController;
@property (retain,nonatomic) UITableView *table;
// Create a set of controllers for a simple fetch controller that
// sorts on a given sort with a key displayed for the value of hat field.
// the tableController is passed in.
+ (JLTableContainer*) createFetchControlledTable:(UITableView *)table
forEntity:(NSString *)entityName forSimpleKey:(NSString *)keyName
inContext:(NSManagedObjectContext *) context
createSectionsBy:(NSString *) sectionName
controlledBy:(NSObject<JLTableController>*) controller;
+ (JLTableContainer*) createFetchControlledTable:(UITableView *)table
forEntity:(NSString *)entityName forSimpleKey:(NSString *)keyName
inContext:(NSManagedObjectContext *) context
createSectionsBy:(NSString *) sectionName
controlledBy:(NSObject<JLTableController>*) controller
accessoryDisplay:(UITableViewCellAccessoryType) accessoryType;
// If this source supports searching via a predicate, then update the
// predicate with that call. Note that if the source DOES NOT
// restrict by predicate, then this call will do nothing.
- (void) updatePredicate:(NSPredicate *) predicate;
// Connect the objects to each other to form the delegation chain of the
// template object.
- (void) connectObjects;
@end
The source file
//
// JLTableContainer.m
// JLFoundation
//
// Created by Jon Lundy on 3/20/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "JLTableContainer.h"
@implementation JLTableContainer
@synthesize callbackHandler;
@synthesize tableSource;
@synthesize cellProvider;
@synthesize tableController;
@synthesize table;
+ (JLTableContainer*) createFetchControlledTable:(UITableView *)table
forEntity:(NSString *)entityName forSimpleKey:(NSString *)keyName
inContext:(NSManagedObjectContext *) context
createSectionsBy:(NSString *) sectionName
controlledBy:(NSObject<JLTableController>*) controller
{
return [JLTableContainer createFetchControlledTable:table forEntity:entityName forSimpleKey:keyName inContext:context
createSectionsBy:sectionName controlledBy:controller
accessoryDisplay:UITableViewCellAccessoryNone];
}
+ (JLTableContainer*) createFetchControlledTable:(UITableView *)table
forEntity:(NSString *)entityName forSimpleKey:(NSString *)keyName
inContext:(NSManagedObjectContext *) context
createSectionsBy:(NSString *) sectionName
controlledBy:(NSObject<JLTableController>*) controller
accessoryDisplay:(UITableViewCellAccessoryType) accessoryType
{
JLTableContainer *returnValue=[[JLTableContainer alloc]init];
SimpleDescriptionCellProvider *simpleCellProvider=[[SimpleDescriptionCellProvider alloc] init];
simpleCellProvider.accessoryType=accessoryType;
returnValue.table=table;
JLFetchedControllerSource *source=[[JLFetchedControllerSource alloc] init];
source.sortField=keyName;
source.managedEntityName=entityName;
source.sectionField=sectionName;
source.fetchContext=context;
JLStandardCallbackHandler *callHandler=[[JLStandardCallbackHandler alloc]init];
returnValue.tableController=controller;
returnValue.cellProvider=simpleCellProvider;
returnValue.tableSource=source;
returnValue.callbackHandler=callHandler;
[returnValue connectObjects];
return [returnValue autorelease];
}
- (void) connectObjects
{
table.delegate=callbackHandler;
table.dataSource=tableSource;
if (callbackHandler!=nil)
{
callbackHandler.tableController=tableController;
callbackHandler.source=tableSource;
}
if (tableSource!=nil)
{
tableSource.cellProvider=cellProvider;
tableSource.table=table;
}
if (cellProvider!=nil)
{
}
if (tableController!=nil)
{
}
}
- (void) updatePredicate:(NSPredicate *) predicate
{
// Check to make source our source is not null and implements the
// requested protocol.
if (self.tableSource!=nil)
{
if ( [tableSource conformsToProtocol:@protocol(RestrictWithPredicate)] ) {
id<RestrictWithPredicate> restricted=(id<RestrictWithPredicate>) self.tableSource;
[restricted updatePredicate:predicate];
}
}
}
- (void) dealloc
{
[callbackHandler release];
[tableSource release];
[cellProvider release];
[tableController release];
[super dealloc];
}
@end
Points of Interest
Static builder methods
The first thing to note is that there is a rather large public static method that lets you construct a fetched result controller which has standard behavior. This API is clumsy, but it should work.
In addition I defined an updatePredicate utility method. This method will first verify that the table source
corresponds to the new protocol, RestrictWithPredicate. If it does, then it will update the predicate with
the passed in data. This allows me to have various optional functions that can be used by manipulating the container object instead of having a lot of casting in the middle.
My goal is to restructure this API a little bit so that it is cleaner, and more modular to use.
if (self.tableSource!=nil)
{
if ( [tableSource conformsToProtocol:@protocol(RestrictWithPredicate)] ) {
id<RestrictWithPredicate> restricted=(id<RestrictWithPredicate>) self.tableSource;
[restricted updatePredicate:predicate];
}
}
Restructuring calls
The method connectObjects is used to restructure the various strategies. Each strategy knows about other strategies in the suite. This call enables you to change strategies, and then make a single call to connect everything back up again.
Usage
Now that I have these methods in place I was able to quickly restructure my main sight word list to instead of selecting all sight words into memory, using a NSFetchedResultsController. I disconnected the .nib file from the File Owner in Interface Builder, and added the following code in viewDidLoad.
self.container=[JLTableContainer createFetchControlledTable:self.tableView
forEntity:@"WordList"
forSimpleKey:@"ListName"
inContext:currentState.control .managedObjectContext
createSectionsBy:@"Category"
controlledBy:self
accessoryDisplay:UITableViewCellAccessoryDetailDisclosureButton
];
[self.container updatePredicate:nil];
I then removed all of the standard table callbacks, and implemented these two callbacks:
Selecting a row
- (void) rowSelected:(id) selectedObject
{
WordList *list=(WordList*)selectedObject;
SightWordDisplay *display=[[SightWordDisplay alloc] initWithNibName:@"SightWordDisplay" bundle:nil];
SightWordProvider *provider=[[SightWordProvider alloc] initWords:list];
display.provider = provider;
// display.title=provider.wordList.ListName;
// Copied from Beginning IPhone Development. Not sure I like the global reference.
[self.navigationController pushViewController:display animated:YES];
[display release];
}
Selecting an accessory
- (void) acessorySelected:(id) selectedObject
{
ListEditor *editor=[[ListEditor alloc ] initWithNibName:@"ListEditor" bundle:nil];
editor.wordlist=(WordList*)selectedObject;
SightWordsUnlimitedAppDelegate *delegate =
[[UIApplication sharedApplication] delegate];
[delegate.rootController pushViewController:editor animated:YES];
[editor.tableView reloadData];
[editor release];
}
The goal is to remove the table management logic from my view controller, and let it concentrate on business logic.
Note that I broke the ability to delete word lists when I did this. I'm going to have to go put it back in. The nice thing about a shared class is that when I add this functionality back in, it will be available to any class using the library.
Labels:
Fetch Controller,
flash cards,
iphone,
Refactoring,
sight words
Monday, November 30, 2009
A useful idea: Sight Words Lists Unlimited
The next idea, which I will probably publish first is a simple flash card application. My daughter and son are learning how to read. In addition to learning phonics, they also need to learn sight words. I've spent a lot of time creating flash cards, and going over them.
In addition my daughter will often have a specific set of 8 sight words to learn for that week. She needs to learn those for this weeks test, but we also need to go over the older sight words so that she continues to gain mastery over them.
There are multiple sight word applications in the store, but most of them suffer from limitations that I can bypass.
Exiting Limitations on many sight word applications
In addition my daughter will often have a specific set of 8 sight words to learn for that week. She needs to learn those for this weeks test, but we also need to go over the older sight words so that she continues to gain mastery over them.
There are multiple sight word applications in the store, but most of them suffer from limitations that I can bypass.
Exiting Limitations on many sight word applications
- A lot of the applications only support 100 or fewer of the sight words, divided into groups, and which have to be purchased separately.
- The applications only allow you to use the pregenerated sight words.
- The ability to limit the words you go over to a specific set is not present, or is not easy to use.
The following are the features of the sight words application I would like to develop.
Minimum Feature List (in priority order)
- It should include all of the common sight words, both from the Dolch and Fry sight word lists with out of the box spoken versions of all those words.
- It should support the ability to add additional words to the list.
- It should support the ability to record your own version of the words using the iPhone.
- It should support the ability to create and manage sub lists of the total word set.
Additional nice to have features
- The ability to designate individual words to be successfully identified or not, and to remove the successfully identified ones from the current pool.
- The ability to change fonts and colors.
- The ability to restore the DB back to its original state.
- Games where a word is pronounced and select a sight word from individual choices. The faster the word is selected the higher the score.
- Better graphics and colors
Labels:
flash cards,
Requirements,
sight words
Subscribe to:
Posts (Atom)
