简体   繁体   中英

UISearchDisplayController delegate methods not being called

I am trying to gain some knowledge on UISearchDisplayController and going through some tutorial with examples, I have the below class ready with a search bar and table view with data on it.

Header file:

#import <UIKit/UIKit.h>    
@interface MyClass : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate, UISearchBarDelegate>    
@property (nonatomic, strong) IBOutlet UITableView *suggestionsTableView;
@property (nonatomic, strong) IBOutlet UISearchBar *searchBar;
@end

Implementation file:

#import "MyClass.h"

@interface DVWNoteTypeSuggestionDisplayController ()
@property (nonatomic, strong) NSArray *items;
@property (nonatomic)BOOL isSearching;
@property (nonatomic, strong) NSMutableArray *filteredList;
@end

@implementation MyClass

- (id)init
{
    self = [super initWithNibName:@"SuggestionDisplayController" bundle:BUNDLE];

    if (self)
    {
        // Set the title.
        self.title = @"test";
    }

    return self;
}


- (void)viewDidLoad
{
self.searchBar = [[UISearchBar alloc] init];
    [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
    self.searchDisplayController.searchResultsDelegate = self;
    self.searchDisplayController.searchResultsDataSource = self;
    self.searchDisplayController.delegate = self;
    self.searchBar.frame = CGRectMake(0, 0, 0, 38);
    self.suggestionsTableView.tableHeaderView = self.searchBar;

    self.items = [[NSArray alloc] initWithObjects:@"Item No. 1", @"Item No. 2", @"Item No. 3", @"Item No. 4", @"Item No. 5", @"Item No. 6", nil];
    self.isSearching = NO;
    self.filteredList = [[NSMutableArray alloc] init];
}

#pragma mark - Table view data source
- (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.
//    // Usually the number of items in your array (the one that holds your list)
//    return [self.items count];
//}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    if (self.isSearching)
    {
        //If the user is searching, use the list in our filteredList array.
        return [self.filteredList count];
    } else
    {
        return [self.items count];
    }
}

//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//    //Where we configure the cell in each row
//    
//    static NSString *CellIdentifier = @"Cell";
//    UITableViewCell *cell;
//    
//    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//    if (cell == nil) {
//        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
//    }
//    // Configure the cell... setting the text of our cell's label
//    cell.textLabel.text = [self.items objectAtIndex:indexPath.row];
//    return cell;
//}

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

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

    // Configure the cell...
    NSString *title;
    if (self.isSearching && [self.filteredList count]) {
        //If the user is searching, use the list in our filteredList array.
        title = [self.filteredList objectAtIndex:indexPath.row];
    } else
    {
        title = [self.items objectAtIndex:indexPath.row];
    }

    cell.textLabel.text = title;

    return cell;
}

- (void)filterListForSearchText:(NSString *)searchText
{
    [self.filteredList removeAllObjects]; //clears the array from all the string objects it might contain from the previous searches

    for (NSString *title in self.items) {
        NSRange nameRange = [title rangeOfString:searchText options:NSCaseInsensitiveSearch];
        if (nameRange.location != NSNotFound) {
            [self.filteredList addObject:title];
        }
    }
}

#pragma mark - UISearchDisplayControllerDelegate

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
    //When the user taps the search bar, this means that the controller will begin searching.
    self.isSearching = YES;
}

- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
    //When the user taps the Cancel Button, or anywhere aside from the view.
    self.isSearching = NO;
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    [self filterListForSearchText:searchString]; // The method we made in step 7

    // Return YES to cause the search result table view to be reloaded.
    return YES;
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
    [self filterListForSearchText:[self.searchDisplayController.searchBar text]]; // The method we made in step 7

    // Return YES to cause the search result table view to be reloaded.
    return YES;
}

@end

Whenever I try to search for any items in the data set (eg: "Item No. 5") its not hitting the breakpoints on any of the delegate ie actually the search is not working. Please suggest what am I missing here as this is just my learning project right now.

It appears that a UISearchDisplayController created programatically in this way is prematurely zeroing the delegate, even though the view controller is retaining the UISearchDisplayController as expected.

Add the following to the end of your viewDidLoad and you'll see that the first log will be a valid object, but the second will be null.

NSLog(@"Delegate should be %@", self.searchDisplayController.delegate);

 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"Delegate is %@", self.searchDisplayController.delegate); }); 

The quickest way I've found to get around this is to store your own reference to the UISearchDisplayController via a private property or ivar.

If you have to create object for search bar controller and set delegate search bar its work.

UISearchBar *searchBar = [[UISearchBar alloc] init];
[[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchDisplayController.searchResultsDelegate = self;         
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.delegate = self;
searchBar.frame = CGRectMake(0, 0, 0, 38);
self.tableView.tableHeaderView = searchBar;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM