How to Use the Uisearchbar and Uisearchdisplaycontroller

How do I use the UISearchBar and UISearchDisplayController

  • First add the UISearchDisplayController to your table view
  • Then set its delegate.
  • Implement the following methods.

Demo Project

In your .h File

    @interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {

NSMutableArray *contentList;
NSMutableArray *filteredContentList;
BOOL isSearching;
}
@property (strong, nonatomic) IBOutlet UITableView *tblContentList;
@property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
@property (strong, nonatomic) IBOutlet UISearchDisplayController *searchBarController;

In your .m File

Filling the sample data (Optional Only For Demo Purpose)

- (void)viewDidLoad {
[super viewDidLoad];
contentList = [[NSMutableArray alloc] initWithObjects:@"iPhone", @"iPod", @"iPod touch", @"iMac", @"Mac Pro", @"iBook",@"MacBook", @"MacBook Pro", @"PowerBook", nil];
filteredContentList = [[NSMutableArray alloc] init];
}

Now implement the Table View Delegate and Datasource

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

// Return the number of sections.
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
if (isSearching) {
return [filteredContentList count];
}
else {
return [contentList count];
}
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

// Configure the cell...
if (isSearching) {
cell.textLabel.text = [filteredContentList objectAtIndex:indexPath.row];
}
else {
cell.textLabel.text = [contentList objectAtIndex:indexPath.row];
}
return cell;

}

Search Function Responsible For Searching

- (void)searchTableList {
NSString *searchString = searchBar.text;

for (NSString *tempStr in contentList) {
NSComparisonResult result = [tempStr compare:searchString options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchString length])];
if (result == NSOrderedSame) {
[filteredContentList addObject:tempStr];
}
}
}

Search Bar Implementation

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
isSearching = YES;
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSLog(@"Text change - %d",isSearching);

//Remove all objects first.
[filteredContentList removeAllObjects];

if([searchText length] != 0) {
isSearching = YES;
[self searchTableList];
}
else {
isSearching = NO;
}
// [self.tblContentList reloadData];
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
NSLog(@"Cancel clicked");
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSLog(@"Search Clicked");
[self searchTableList];
}

How UISearchDisplayController steals UISearchBar events

OK, I figured out myself.

You can do that just by adding the UISearchBar delegate property to KVO observation, and then make your implementation as a delegate proxy.

Example Code:


    if (searchBar.delegate) {
self.searchBarDelegate = searchBar.delegate;
}

searchBar.delegate = self;

[searchBar addObserver:self forKeyPath:@"delegate" options:NSKeyValueObservingOptionNew context:kSearchBarKVOContext];

#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == kSearchBarKVOContext) {
[self updateSearchBarDelegate];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}

- (void)updateSearchBarDelegate
{
if (self.searchBar.delegate == self) {
self.searchBarDelegate = nil;
} else {
self.searchBarDelegate = self.searchBar.delegate;
self.searchBar.delegate = self;
}
}

#pragma mark - NSObject Overrides
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *result = [super methodSignatureForSelector:aSelector];

if (!result) {
NSObject *obj = (NSObject *)self.searchBarDelegate;

result = [obj methodSignatureForSelector:aSelector];
}

return result;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([self.searchBarDelegate respondsToSelector:[anInvocation selector]]) {
[anInvocation invokeWithTarget:self.searchBarDelegate];
} else {
[super forwardInvocation:anInvocation];
}
}

- (BOOL)respondsToSelector:(SEL)aSelector {
return ([super respondsToSelector:aSelector] ||
[self.searchBarDelegate respondsToSelector:aSelector]);
}

How to use UISearchDisplayController from a controller within an UITabBar controller?

Ok, I have found how to solve it. In my case, the problem was due to the fact that I was using a controller embedded within the UITabBarController as one of its managed tabs (i.e. as a child).

Removing the controller from the UITabBarController, then adding an UINavigationController to the UITabBarController instead, and finally putting my controller as a child of the UINavigationController solved completely the issue.

I do not understand why this is so (there is no related information in the documentation, as often happens); however, it now works like a charm.
With kind regards.



Related Topics



Leave a reply



Submit