Codesnipp.it Social Code Sharing

Amber Weinberg

Custom Table View With Search & Index

by Amber Weinberg on Jul 27, 2010

/* From Beginning iPhone Development 3 by Dave Mark*/ /*In your sectionsViewController.h file*/ #import <UIKit/UIKit.h> @interface _8_SectionsViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate> { UITableView *table; UISearchBar *search; NSDictionary *allNames; NSMutableDictionary *names; NSMutableArray *keys; BOOL isSearching; } @property (nonatomic, retain) IBOutlet UITableView *table; @property (nonatomic, retain) IBOutlet UISearchBar *search; @property (nonatomic, retain) NSDictionary *allNames; @property (nonatomic, retain) NSMutableDictionary *names; @property (nonatomic, retain) NSMutableArray *keys; - (void)resetSearch; - (void)handleSearchForTerm:(NSString *)searchTerm; @end /*In your sectionsViewController.m file*/ #import "_8_SectionsViewController.h" #import "NSDictionary-MutableDeepCopy.h" @implementation _8_SectionsViewController @synthesize names; @synthesize keys; @synthesize table; @synthesize search; @synthesize allNames; #pragma mark - #pragma mark Custom Methods - (void)resetSearch { NSMutableDictionary *allNamesCopy = [self.allNames mutableDeepCopy]; self.names = allNamesCopy; [allNamesCopy release]; NSMutableArray *keyArray = [[NSMutableArray alloc] init]; [keyArray addObject:UITableViewIndexSearch]; [keyArray addObjectsFromArray:[[self.allNames allKeys] sortedArrayUsingSelector:@selector(compare:)]]; self.keys = keyArray; [keyArray release]; } - (void)handleSearchForTerm:(NSString *)searchTerm { NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init]; [self resetSearch]; for (NSString *key in self.keys) { NSMutableArray *array = [names valueForKey:key]; NSMutableArray *toRemove = [[NSMutableArray alloc] init]; for (NSString *name in array) { if ([name rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location == NSNotFound) [toRemove addObject:name]; } if ([array count] == [toRemove count]) [sectionsToRemove addObject:key]; [array removeObjectsInArray:toRemove]; [toRemove release]; } [self.keys removeObjectsInArray:sectionsToRemove]; [sectionsToRemove release]; [table reloadData]; } - (void)viewDidLoad { NSString *path = [[NSBundle mainBundle] pathForResource:@"sortednames" ofType:@"plist"]; NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path]; self.allNames = dict; [dict release]; [self resetSearch]; [table reloadData]; [table setContentOffset:CGPointMake(0.0, 44.0) animated:NO]; } - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } - (void)viewDidUnload { // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; self.table = nil; self.search = nil; self.allNames = nil; self.names = nil; self.keys = nil; } - (void)dealloc { [table release]; [search release]; [allNames release]; [names release]; [keys release]; [super dealloc]; } #pragma mark - #pragma mark Table view Data Source Methods - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return ([keys count] > 0 ? [keys count] : 1); } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if ([keys count] == 0) return 0; NSString *key = [keys objectAtIndex:section]; NSArray *nameSection = [names objectForKey:key]; return [nameSection count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger section = [indexPath section]; NSUInteger row = [indexPath row]; NSString *key = [keys objectAtIndex:section]; NSArray *nameSection = [names objectForKey:key]; static NSString *SectionsTableIdentifier = @"SectionsTableIdentifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SectionsTableIdentifier] autorelease]; } cell.textLabel.text = [nameSection objectAtIndex:row]; return cell; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { if ([keys count] == 0) return nil; NSString *key = [keys objectAtIndex:section]; if (key == UITableViewIndexSearch) return nil; return key; } - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { if (isSearching) return nil; return keys; } #pragma mark - #pragma mark TableView Delegate Methods - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { [search resignFirstResponder]; isSearching = NO; search.text = @""; [tableView reloadData]; return indexPath; } #pragma mark - #pragma mark Search Bar Delegate Methods - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchTerm { if ([searchTerm length] == 0) { [self resetSearch]; [table reloadData]; return; } [self handleSearchForTerm:searchTerm]; } - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { isSearching = NO; search.text = @""; [self resetSearch]; [table reloadData]; [searchBar resignFirstResponder]; } - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { isSearching = YES; [table reloadData]; } - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { NSString *key = [keys objectAtIndex:index]; if (key == UITableViewIndexSearch) { [tableView setContentOffset:CGPointZero animated:NO]; return NSNotFound; } else return index; } @end /* In your NSDictionary-MutableDeepCopy.h file */ #import <Foundation/Foundation.h> @interface NSDictionary(MutableDeepCopy) - (NSMutableDictionary *)mutableDeepCopy; @end /* In your NSDictionary-MutableDeepCopy.m file */ #import "NSDictionary-MutableDeepCopy.h" @implementation NSDictionary (MutableDeepCopy) - (NSMutableDictionary *) mutableDeepCopy { NSMutableDictionary *ret = [[NSMutableDictionary alloc] initWithCapacity:[self count]]; NSArray *keys = [self allKeys]; for (id key in keys) { id oneValue = [self valueForKey:key]; id oneCopy = nil; if ([oneValue respondsToSelector:@selector(mutableDeepCopy)]) oneCopy = [oneValue mutableDeepCopy]; else if ([oneValue respondsToSelector:@selector(mutableCopy)]) oneCopy = [oneValue mutableCopy]; if (oneCopy == nil) oneCopy = [oneValue copy]; [ret setValue:oneCopy forKey:key]; } return ret; }

Can't see the comments? Please login first :)