Some Choice tidbits:
Shrinking the view
In viewDidLoad place the following code:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardAppearing:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDisappearing:) name:UIKeyboardWillHideNotification object:nil];
and then add the following two methods. Note that suggestions is the outlet for the list being displayed.
- (void)keyboardDisappearing:(NSNotification *)notification {
suggestions.frame=originalSize;
}
- (void)keyboardAppearing:(NSNotification *)notification {
NSDictionary *keys=[notification userInfo];
NSValue *value=[keys objectForKey:UIKeyboardBoundsUserInfoKey];
CGRect bounds;
[value getValue:&bounds];
CGRect myFrame=[suggestions frame];
originalSize=myFrame;
suggestions.frame=CGRectMake(myFrame.origin.x,myFrame.origin.y,myFrame.size.width,
myFrame.size.height-bounds.size.height);
}
Delegating item creation and actions:
By defining a simple protocol and ensuring a delegate exists we can delegate out the selection of an
existing item and also the actual action that takes place upon selection.
@protocol SuggesionActionHandler<NSObject>
- (id) createNewItem:(NSString *) searchValue;
- (void) doActionForItem:(id) item;
@end
Adding an item Adding an item: Note that this combines the animation and action into the same area. It really should be separated out. I'm not sure I like how I search for the currently existing item. At the very least it should be broken out into another method.
- (IBAction) addCurrentItem:(id) sender
{
NSManagedObject *matchingItem=nil;
NSString *currentText=searchBar.text;
UIGraphicsBeginImageContext(searchBar.bounds.size);
[searchBar.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *imageView=[[UIImageView alloc] initWithImage :viewImage];
imageView.frame=searchBar.frame;
[self.view addSubview:imageView];
[UIView beginAnimations:nil context:imageView];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.25];
[imageView setFrame:addButton.frame];
// Search for the existing item if one.
if (fetchController!=nil)
{
if (fetchController.sections!=nil)
{
for (id<NSFetchedResultsSectionInfo> sectionInfo in fetchController.sections)
{
for (NSManagedObject *object in [sectionInfo objects])
{
NSString *keyForSearch=[object valueForKey:self.searchVariable];
if ([keyForSearch isEqualToString: currentText])
{
matchingItem=object;
break;
}
}
if (matchingItem!=nil)
break;
}
}
}
if (delegate!=nil)
{
if (matchingItem==nil)
{
matchingItem=[delegate createNewItem:currentText];
}
[delegate doActionForItem:matchingItem];
}
else
{
NSLog(@"Delegate is nil, no action can be performed ");
}
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
[UIView commitAnimations];
}
Updating a Fetch controller with a search predicate:
This was slightly tricky, since the examples assumed a hardcoded search variable. I had to format the string twice so that I could build the format string with the field name prior to doing substitution.
NSFetchRequest *request=[[NSFetchRequest alloc] init];
NSEntityDescription *entity=[NSEntityDescription entityForName:managedTable
inManagedObjectContext:coreControl.managedObjectContext];
[request setEntity:entity];
[request setFetchBatchSize:20];
NSSortDescriptor *sortDesc=[[NSSortDescriptor alloc] initWithKey:searchVariable ascending:YES];
NSArray *sortDescs=[[NSArray alloc] initWithObjects:sortDesc,nil];
NSString *searchString=[searchText stringByAppendingString:@"*"];
NSString *predicateFormat=[[NSString alloc] initWithFormat:@"%@ like[cd] %%@",searchVariable];
NSLog(@"Searching table %@ %@ for %@",managedTable,searchVariable,searchString);
NSPredicate *predicate = [NSPredicate
predicateWithFormat:predicateFormat,
searchString];
NSLog(@"Pred Desc %@", [predicate description]);
[request setPredicate:predicate];
[request setSortDescriptors:sortDescs];
if (fetchController!=nil)
{
[fetchController release];
}
self.fetchController=[[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:coreControl.managedObjectContext sectionNameKeyPath:nil cacheName:managedTable];
self.fetchController.delegate=self;
NSError *error;
[self.fetchController performFetch:&error] ;
// NSLog(@"Unresolved error %@", error);
// NSLog(@"Fetch count %d",fetchController.sections);
[self.suggestions reloadData];
[predicateFormat release];
[request release];
[sortDesc release];
[sortDescs release];