18

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.

yedpodtrzitko
  • 9,035
  • 2
  • 40
  • 42
R2D2
  • 2,620
  • 4
  • 24
  • 46
  • 1
    https://developer.apple.com/library/ios/samplecode/TableSearch_UISearchController/Introduction/Intro.html – soulshined Aug 23 '15 at 18:39
  • 1
    I found this following example code, which has been the most useful example I have found so far: https://github.com/Ja5onHoffman/UISearchController-Demo – R2D2 Aug 24 '15 at 11:45

2 Answers2

25

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.

P.J.Radadiya
  • 1,493
  • 1
  • 12
  • 21
codelover
  • 1,113
  • 10
  • 28
  • 1
    Could you tell, what is `CLCustomerResultrowsItemsCellController`? It gives me error and can not be imported. – Nikita Vlasenko Nov 24 '15 at 02:39
  • 1
    Oh CLCustomerResultrowsItemsCellController is nothing just a tableviewcontroller class with two methods and a property filteredresults nsmutablearray. The number of rows to mention the items found on reload and cellforrowatindexpath to create a cell by using a confirgurecell:... check the IOS TableViewcontroller with uisearchcontroller example its more easy to solve an understand. – codelover Nov 24 '15 at 09:51
  • If you like the answer and solved your purpose please accept the answer and tick :) – codelover Nov 24 '15 at 09:51
  • Oh, it i not my question, can I still accept the answer? I am going to implement it this way and if it works, I will definitely vote it up. – Nikita Vlasenko Nov 24 '15 at 19:18
  • 1
    Are you using any `.xib` files at all? I would think that `UISearchController` should have its `.xib`. It would be much better if you could please add some additional files, like this custom `CLCustomerResultrowsItemsCellController` and clarify workflow a bit, explain it in more detail, especially, how `UISearchController` interacts with another custom `UITableViewController`, and then, which controller should have `.xib` to customize actual view. Should we put `UISearchBar` OR `UISearchBar and Search Display Controller` in the `.xib`? – Nikita Vlasenko Nov 24 '15 at 19:34
  • What is `self.contactsTableView.tableHeaderView = self.searchController.searchBar`? It gives me error. Seems like I do not have `constactsTableView` property. – Nikita Vlasenko Nov 24 '15 at 19:54
  • What is `_fetchedResultsController` in `UISearchResultsUpdating`? It gives me error too. – Nikita Vlasenko Nov 24 '15 at 20:20
  • I asked another question trying to get more clarification, take a look: http://stackoverflow.com/questions/33906239/further-clarification-of-how-to-implement-uisearchcontroller-with-objective-c – Nikita Vlasenko Nov 25 '15 at 00:06
  • What is self.contactsTableView.tableHeaderView = self.searchController.searchBar? It gives me error. Seems like I do not have constactsTableView property. – - This is to assign the search bar to the main table for the searching , you can use your own as well and assign to the search controller searchbar.. – codelover Nov 25 '15 at 06:25
  • I solved it already the way Apple docs recommend and will post the answer soon to the question that I asked in relation to yours. The line is how Apple suggests to do it: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UISearchController/ I tried your code straight the way you wrote it and whatever I did I was not able to make it working, so I assume that your answer is still not accepted because there is not enough of detail on how you did it. Could you add the minute details and clarifications? – Nikita Vlasenko Nov 25 '15 at 20:10
  • Ah, no sorry, misread it. In my original post I have not implemented Apple's suggestion. It IS present in your code: `self.contactsTableView.tableHeaderView = self.searchController.searchBar` in `4) Initialise the code in this step in ViewDidload` 7th line, no? – Nikita Vlasenko Nov 25 '15 at 20:19
  • 7th line, no? I didn't get this , did it solved your purpose ? – codelover Nov 26 '15 at 04:24
  • This was in response to your post: `What is self.contactsTableView.tableHeaderView = self.searchController.searchBar? It gives me error. Seems like I do not have constactsTableView property. – - This is to assign the search bar to the main table for the searching , you can use your own as well and assign to the search controller searchbar.. –` You have `conactsTableView` property above in your code. No, it is not important anymore. I solved it differently, but used your template. Posted my answer to the linked question that I asked: – Nikita Vlasenko Nov 26 '15 at 06:05
  • http://stackoverflow.com/questions/33906239/further-clarification-of-how-to-implement-uisearchcontroller-with-objective-c – Nikita Vlasenko Nov 26 '15 at 06:07
0

SOLVED!

I created(and it's public for you to download) a Sample code on Objective-C, that I translated from a swift tutorial video.