How to implement UISearchController with objective c

R2D2 picture R2D2 · Aug 23, 2015 · Viewed 23.8k times · Source

I have an existing app, written in objective-c, with a table view.

I am now trying to go back to this app and add a search bar to the table.

The problem is that now there is the new UISearchController protocol, there seems to be very little information online in how to implement this within objective-c - all tutorials and examples that I can find are all for Swift.

I have added the delegates to the .h file:

UISearchBarDelegate, UISearchResultsUpdating

And I have the following code in viewDidLoad, which works and adds a search bar:

// Search controller
searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
searchController.searchResultsUpdater = self;
searchController.dimsBackgroundDuringPresentation = NO;
searchController.searchBar.delegate = self;

// Add the search bar
self.tableView.tableHeaderView = searchController.searchBar;
self.definesPresentationContext = YES;
[searchController.searchBar sizeToFit];

And that is as far as I have got!

I would appreciate any pointers, example code or tutorials on how to implement the new UISearchController in an existing objective-c app tableview.

Answer

Vicky Dhas picture Vicky Dhas · Nov 18, 2015

Initialise Following things as per steps mentioned.

1) Protocol declaration in <UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating> in the .h interface class

2) Declare following properties

//Fetch result controller 
@property (nonatomic, strong) UISearchController *searchController;

//for the results to be shown with two table delegates
@property (nonatomic, strong) CLCustomerResultrowsItemsCellController *searchResultsController;

//this custom controller is only suppose to have number of rows and cell for row function of table datasource

3) For state restoration

 @property BOOL searchControllerWasActive;
 @property BOOL searchControllerSearchFieldWasFirstResponder;

4) Initialise the code in this step in ViewDidload

_searchResultsController = [[CLChatContactsSearchResultController alloc] init];
_searchController = [[UISearchController alloc] initWithSearchResultsController:_searchResultsController];

self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.placeholder = nil; 
[self.searchController.searchBar sizeToFit];
self.contactsTableView.tableHeaderView = self.searchController.searchBar;


// we want to be the delegate for our filtered table so didSelectRowAtIndexPath is called for both tables
self.searchResultsController.tableView.delegate = self;
self.searchController.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = YES; // default is YES
self.searchController.searchBar.delegate = self; // so we can monitor text changes + others

// Search is now just presenting a view controller. As such, normal view controller
// presentation semantics apply. Namely that presentation will walk up the view controller
// hierarchy until it finds the root view controller or one that defines a presentation context.
//
self.definesPresentationContext = YES;  // know where you want UISearchController to be displayed

5) Use Button even to initiate the controller and past these functions for future usage if any see comments

#pragma mark - UISearchBarDelegate

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [searchBar resignFirstResponder];
}


#pragma mark - UISearchControllerDelegate

// Called after the search controller's search bar has agreed to begin editing or when
// 'active' is set to YES.
// If you choose not to present the controller yourself or do not implement this method,
// a default presentation is performed on your behalf.
//
// Implement this method if the default presentation is not adequate for your purposes.
//
- (void)presentSearchController:(UISearchController *)searchController {

}

- (void)willPresentSearchController:(UISearchController *)searchController {
    // do something before the search controller is presented
}

- (void)didPresentSearchController:(UISearchController *)searchController {
    // do something after the search controller is presented
}

- (void)willDismissSearchController:(UISearchController *)searchController {
    // do something before the search controller is dismissed
}

- (void)didDismissSearchController:(UISearchController *)searchController {
    // do something after the search controller is dismissed
}

6) On searching in text you get this callback

#pragma mark - UISearchResultsUpdating

- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {

    // update the filtered array based on the search text
    NSString *searchText = searchController.searchBar.text;

    id <NSFetchedResultsSectionInfo> sectionInfo = [_fetchedResultsController.sections objectAtIndex:0];

    if (searchText == nil) {

        // If empty the search results are the same as the original data
        self.searchResults = [sectionInfo.objects mutableCopy];

    } else {

        NSMutableArray *searchResults = [[NSMutableArray alloc] init];

        NSArray *allObjects = sectionInfo.objects;

        for (PhoneNumber *phoneMO in allObjects) {

            if ([phoneMO.number containsString:searchText] || [[phoneMO.closrr_id filteredId] containsString:searchText] || [[phoneMO.contact.fullname lowercaseString] containsString:[searchText lowercaseString]]) {
                [searchResults addObject:phoneMO];
            }
        }

        self.searchResults = searchResults;

    }

    // hand over the filtered results to our search results table
    CLCustomerResultrowsItemsCellController *tableController = (CLCustomerResultrowsItemsCellController *)self.searchController.searchResultsController;
    tableController.filteredContacts = self.searchResults;
    [tableController.tableView reloadData];
}

7) You have to declare the filteredContacts property in the Custom class that will fill the searched items .

8) Thats it , in did select row compare the table view if its the main controller or custom controller class table view and do the operation for the selected item.

Hope this is helpful.