iOS adding a UISearchController is unhiding the NavigationBar - ios

I am having this weird side effect when I use a UISearchController to update my table view (If I select something from the tableview without searching the bug doesn't manifest itself). But when I search, select a cell, and then popViewControllerAnimated: for some reason the NavigationBar is no longer hidden. I want to think that this is a bug within iOS and not specific to my code. But I thought I would see if anyone can spot a bug in my code or has any ideas of something I might be doing wrong. I've added [self.navigationController setNavigationBarHidden:YES]; to my viewWillAppear of the rootView but the bar doesn't go away until the animation is over.
My TableView/UISearchController code:
#interface LBSelectUniversityView()<UISearchResultsUpdating, UISearchBarDelegate>
#property (strong, nonatomic) UISearchController *searchController;
#end
#implementation LBSelectUniversityView {
NSArray *schoolNames;
NSArray *searchResults;
}
- (void)viewDidLoad {
[super viewDidLoad];
schoolNames = [[LBUtilities sharedInstance] schoolNames];
searchResults = schoolNames;
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.delegate = self;
self.tableView.tableHeaderView = self.searchController.searchBar;
self.definesPresentationContext = YES;
[self.searchController.searchBar sizeToFit];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return searchResults.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];
}
...
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText{
if ([searchText isEqualToString:#""]) return;
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResults = [schoolNames filteredArrayUsingPredicate:resultPredicate];
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController{
NSString *searchString = searchController.searchBar.text;
[self filterContentForSearchText:searchString];
[self.tableView reloadData];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
[self.navigationController popViewControllerAnimated:YES];
}
#end

Does the problem go away if you set searchController.hidesNavigationBarDuringPresentation = NO?
Maybe the following is happening:
When you start searching, searchController.active is set to YES. Thus searchController calls [... setNavigationBarHidden:YES] because UISearchController.hidesNavigationBarDuringPresentation = YES by default.
popViewControllerAnimated: is called.
searchController.active is set to NO, so searchController calls [... setNavigationBarHidden:NO]. This causes the navigation bar to be shown.

I think once your search results comes back you are reloading your main table and not search table. This is how you should load data on search results table.
self.searchController.searchResultsTableView reloadData];

Related

Transitioning from UISearchDisplayController ==> UISearchController can't get search bar to show

I have an app that was written for iOS 7 the I need to update as UISearchDisplayController is deprecated for UISearchController.
I have went through several tutorials and tried but I cannot get this to work, however I am close.
I am following this pattern.
The problem I am running into is that the pattern I am following loads the data from a son file into an NSDict object, but my data is in an Array. No problem, I just modified the search to use a predicate (I hard coded something for now, get all records with an E in the name).
But I am getting the following error:
2017-09-12 13:01:41.538 Scoular[7644:1963822] -[employee isEqualToString:]: unrecognized selector sent to instance 0x608000105580
2017-09-12 13:01:41.604 Scoular[7644:1963822] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[employee isEqualToString:]: unrecognized selector sent to instance 0x608000105580'
In the SearchResultsTableViewController.m file, at the line
cell.textLabel.text = self.searchResults[indexPath.row];
from the m file below. I am stumped. Any help would be greatly appreciated.
#import "SearchResultsTableViewController.h"
#interface SearchResultsTableViewController ()
#property (nonatomic, strong) NSArray *array;
#end
#implementation SearchResultsTableViewController
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.searchResults count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchResultCell" forIndexPath:indexPath];
cell.textLabel.text = self.searchResults[indexPath.row];
return cell;
}
#end
Header File
#import UIKit;
#class EmployeeDetailViewController;
#import <CoreData/CoreData.h>
#import "EmployeeDatabase.h"
#interface EmployeeListViewController : UITableViewController
#end
Implementation File
#import "EmployeeListViewController.h"
#import "EmployeeDetailViewController.h"
#import "SearchResultsTableViewController.h"
#interface EmployeeListViewController () <UISearchResultsUpdating>
#property (nonatomic, strong) NSMutableArray *employees;
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) NSMutableArray *searchResults;
#property (nonatomic,retain) NSMutableDictionary *sections;
#end
#implementation EmployeeListViewController
BOOL isSearching;
//Do I still need this
- (void)awakeFromNib {
if ([[UIDevice currentDevice] userInterfaceIdiom] ==
UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
self.preferredContentSize = CGSizeMake(320.0, 600.0);
}
[super awakeFromNib];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Get array of employees and sections
self.employees = [EmployeeDatabase getEmployees];
self.sections = [EmployeeDatabase getSections:_employees];
// There's no transition in our storyboard to our search results tableview or navigation controller
// so we'll have to grab it using the instantiateViewControllerWithIdentifier: method
UINavigationController *searchResultsController = [[self storyboard] instantiateViewControllerWithIdentifier:#"TableSearchResultsNavController"];
// Our instance of UISearchController will use searchResults
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
// The searchcontroller's searchResultsUpdater property will contain our tableView.
self.searchController.searchResultsUpdater = self;
// The searchBar contained in XCode's storyboard is a leftover from UISearchDisplayController.
// Don't use this. Instead, we'll create the searchBar programatically.
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x,
self.searchController.searchBar.frame.origin.y,
self.searchController.searchBar.frame.size.width, 44.0);
self.tableView.tableHeaderView = self.searchController.searchBar;
// Set the back bar button
UIBarButtonItem *backButton =
[[UIBarButtonItem alloc] initWithTitle:#"Employees"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
self.navigationItem.backBarButtonItem = backButton;
}
#pragma mark - Table Sections
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSInteger tmpCount;
if (isSearching) {
tmpCount = 1;
} else {
tmpCount = [[self.sections allKeys] count];
}
return tmpCount;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.employees count];
}
#pragma mark - Table View
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
employee *thisEmployee =
[[self.sections
valueForKey:[[[self.sections allKeys]
sortedArrayUsingSelector:
#selector(localizedCaseInsensitiveCompare:)]
objectAtIndex:indexPath.section]]
objectAtIndex:indexPath.row];
cell.textLabel.text = thisEmployee.fulNme;
return cell;
}
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section {
NSString *tmpString;
//if (tableView == self.searchDisplayController.searchResultsTableView) {
//tmpString = nil;
//} else {
tmpString =
[[[self.sections allKeys]
sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:
)] objectAtIndex:section];
//}
return tmpString;
}
#pragma mark - Right side bar alphabetical index
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
NSArray *tmpTitle;
if (isSearching) {
tmpTitle = nil;
} else {
tmpTitle = [[self.sections allKeys]
sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
return tmpTitle;
}
#pragma mark - UISearchControllerDelegate & UISearchResultsDelegate
// Called when the search bar becomes first responder
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
// Set searchString equal to what's typed into the searchbar
NSString *searchString = self.searchController.searchBar.text;
[self updateFilteredContentForAirlineName:searchString];
// If searchResultsController
if (self.searchController.searchResultsController) {
UINavigationController *navController = (UINavigationController *)self.searchController.searchResultsController;
// Present SearchResultsTableViewController as the topViewController
SearchResultsTableViewController *vc = (SearchResultsTableViewController *)navController.topViewController;
// Update searchResults
vc.searchResults = self.searchResults;
// And reload the tableView with the new data
[vc.tableView reloadData];
}
}
// Update self.searchResults based on searchString, which is the argument in passed to this method
- (void)updateFilteredContentForAirlineName:(NSString *)employeeName
{
if (employeeName == nil) {
// If empty the search results are the same as the original data
self.searchResults = [self.employees mutableCopy];
} else {
NSArray *searchResults2 = [[NSMutableArray alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"fulNme contains 'E'"];
searchResults2 = [self.employees filteredArrayUsingPredicate:predicate];
self.searchResults = [searchResults2 mutableCopy];
}
}
#end
In your updateFilteredContentForAirlineName function you are searching from self.employees array which probably contains employee custom class object. For that reason your self.searchResults array also containing same class object.
But in your cellForRowAtIndexPath of SearchResultsTableViewController your are doing cell.textLabel.text = self.searchResults[indexPath.row]; that means you are adding employee object as string in cell.textLabel which causing your app to crash. Instead you can try this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchResultCell" forIndexPath:indexPath];
employee *thisEmployee = self.searchResults[indexPath.row];
cell.textLabel.text = thisEmployee.fulNme;
return cell;
}

SearchController not searching custom UITableViewCells

Not sure if the title makes to much sense so here is a description of what is going on:
I have a UITableViewController that is using a custom UITableViewCell for its data. I am then manually adding a searchBar to the header of the UITableView and setting it up based on this tutorial : http://useyourloaf.com
Now the searchBar is setup, it looks like it is working but the issue is that I am not actually getting any results and the table is not loading properly (the search results, it load the base data fine)
Here is my code for comparison. I know I must be missing something simple...
** I am hardcoding the data for my cells at the moment, this will change to a core data model once I can fix this issue... although this may be the base of my issue as I am hardcoding the cells at each IP **
#implementation CharitiesTableViewController{
NSArray *charities;
NSArray *searchResults;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setColors];
[_charityTable registerNib:[UINib nibWithNibName:#"CharityTableViewCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:#"charityCell"];
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 350.0;
// self.tableView.contentInset = UIEdgeInsetsMake(-2.0f, 0.0f, 0.0f, 0.0);
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.delegate = self;
self.searchController.delegate = self;
self.tableView.tableHeaderView = self.searchController.searchBar;
self.definesPresentationContext = YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void) setColors {
}
#pragma mark - Search Controller
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSString *searchString = searchController.searchBar.text;
[self searchForText:searchString];
[self.tableView reloadData];
}
- (void)searchForText:(NSString *)searchText {
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
searchResults = [charities filteredArrayUsingPredicate:resultPredicate];
}
- (void)willPresentSearchController:(UISearchController *)searchController {
self.navigationController.navigationBar.translucent = YES;
}
-(void)willDismissSearchController:(UISearchController *)searchController {
self.navigationController.navigationBar.translucent = NO;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView == _charityTable)
{
return 1;
}
return [searchResults count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section {
return SectionSpacer;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return SectionSpacer;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.section) {
case 0:{
CharityTableViewCell *cell = (CharityTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"charityCell"];
cell.charityImage.image = [UIImage imageNamed:#"cleanup"];
cell.charityName.text = #"Garbage cleanup - Crowchild";
cell.charityTagLine.text = #"City of Calgary";
cell.charityDescriptionShort.text = #"We are rounding up anyone that wants to help clean up the grass and nearby areas close to crowchild.";
return cell;
}
default:{
UITableViewCell *cell;
return cell;
}
}
}
#end
Thanks for you help!
I am silly.... I was trying to do this without initializing the data like a com mentor said. The code is correct and if anyone has any similar issues make sure your array of data actually has data in it...

Problems with Search Display Controller

I am learning to use Search Bars a Search Display Controllers in iOS. I made a simple test project with two views, one view contains a UITableView and a UISearchBar, when you select an row from the table view, the new view shows a label with the name of the row. I'm getting a couple of problems, first when I start to add text in the search bar and the search display appears, the search bar is gone. The filtered results are shown, but when I select a row it does not take me to the next view, this only happens when the table is filtered. Here is the code:
ViewController.h
#import <UIKit/UIKit.h>
#import "DetailViewController.h"
#interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchDisplayDelegate, UISearchBarDelegate>
#property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) NSArray *objects;
#property (nonatomic, strong) NSArray *filteredObjects;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_objects = [[NSMutableArray alloc] initWithObjects:#"One", #"Two", #"Three", #"Four", #"Five", #"Six", #"Seven", #"Eight", #"Nine", #"Ten", nil];
_tableView.delegate = self;
_tableView.dataSource = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [_filteredObjects count];
} else {
return [_objects count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [_filteredObjects objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [_objects objectAtIndex:indexPath.row];
}
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ToDetail"]) {
DetailViewController *detailViewController = [segue destinationViewController];
if (self.searchDisplayController.active) {
NSIndexPath *indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
detailViewController.detailString = [_filteredObjects objectAtIndex:indexPath.row];
} else {
NSIndexPath *indexPath = [_tableView indexPathForSelectedRow];
detailViewController.detailString = [_objects objectAtIndex:indexPath.row];
}
}
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchText];
_filteredObjects = [_objects filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
Thanks for the help!
when I select a row it does not take me to the next view, this only happens when the table is filtered
Because you have no implementation of tableView:didSelectRowAtIndexPath:.
Remember, there is really no such thing as a "filtered table view". There are two table views: the normal one, and the one that appears because of the search display controller. That is a different table view (basically appearing in front of yours), and you must configure it for whatever you want it to do and however you want it to look.

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 i.e. 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;

linking from dynamic table cells to specific view controllers

I am trying to link from a dynamic table view cell (as part of a search result table) to a specific view controller
The code I have implemented so far is:
SearchViewController.h
import <UIKit/UIKit.h>
#interface SearchViewController : UITableViewController <UISearchDisplayDelegate, UISearchDisplayDelegate>
#property (strong,nonatomic) NSArray *sysTArray;
#property (strong,nonatomic) NSMutableArray *filteredsysTArry;
#property IBOutlet UISearchBar *sysTSearchBar;
#end
SearchViewController.M
#import "SearchViewController.h"
#import "sysT.h"
#interface SearchViewController ()
#end
#implementation SearchViewController
#synthesize sysTArray;
#synthesize filteredsysTArry;
#synthesize sysTSearchBar;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
sysTArray = [NSArray arrayWithObjects:
[sysT sysTOfCategory:#"p" name:#"H1"],
[sysT sysTOfCategory:#"p" name:#"W2"],
[sysT sysTOfCategory:#"p" name:#"W3"],
[sysT sysTtOfCategory:#"p" name:#"C4"],
[sysT sysTOfCategory:#"c" name:#"O5"],
[sysT sysTOfCategory:#"c" name:#"C6"],
[sysT sysTOfCategory:#"a" name:#"L7"], nil];
self.filteredSysTArry = [NSMutableArray arrayWithCapacity:[sysTArray count]];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [filteredsysTArry count];
}else{
return [sysTArray count];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (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];
}
SysT *sysT = nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
sysT = [filteredsysTArry objectAtIndex:indexPath.row];
}else{
sysT = [sysTArray objectAtIndex:indexPath.row];
}
cell.textLabel.text = sysT.name;
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
return cell;
}
#pragma mark Search Filtering
-(void)filterContentForSearchText:(NSString*) searchText scope:(NSString*)scope {
[self.filteredSysTArry removeAllObjects];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.name contains[c] %#", searchText];
filteredSysTArry = [NSMutableArray arrayWithArray:[sysTArray filteredArrayUsingPredicate:predicate]];
}
#pragma mark - UISearchDisplayController Delegate Methods
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForSearchText:searchString scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex: [self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
-(BOOL) searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
[self filterContentForSearchText:self.searchDisplayController.searchBar.text scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
return YES;}
#end
How do I initiate a specific view controller depending on the data inside the dynamic cell?
To further elaborate, if a user searched H1, and then clicked on that dynamic cell, how would I display the relevant H1 view controller?
As you can probably tell from my very rough code, I'm on a steep learning curve. If you could make your answers as baby proof as possible that would be fantastic, and would really help me out. (Also, I am using storyboards).
Thanks!
You need to implement tableView:didSelectRowAtIndexPath: which is called when you select a row. You can get the data for that row by querying your data source, using the indexPath passed into that method. You can then use whatever logic you need to choose which view controller to go to next. You do that by calling performSegueWithIdentifier.

Resources