I'm using a UISearchDisplayController in my app. When the user selects an item in the search results returned I deactivate the UISearchDisplayController. Deactivating the controller clears the text the user has typed. I want to keep it there. I try to assign the text back into the UISearchBar by setting it again after the controller has been deactivated. The text does appear in the search bar but this will cause the UISearchDisplayController to active again even though I have disable the delegate! This issue only happens on iOS 7. Before iOS7, the code below works charmingly.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSUInteger row = [indexPath row];
NSString *term = [keywordSuggestion objectAtIndex:row];
[search resignFirstResponder];
[self handleSearchForTerm:term];
}
-(void)handleSearchForTerm:(NSString *)searchTerm {
[searchDisplayController setActive:NO animated:YES]; //searchbar text will be lost
searchDisplayController.delegate = nil;
search.text = term;
searchDisplayController.delegate = self;
}
Is there are a way that I can set the text of the UISearchBar without having the UISearchDisplayController that's associated with become active?
Here is an example of some working code:
#import "RBTableViewController.h"
#interface RBTableViewController () <UISearchDisplayDelegate>
#end
#implementation RBTableViewController {
UISearchBar *_searchBar;
UISearchDisplayController *_searchController;
NSMutableArray *_searchResults;
NSMutableArray *_model;
NSString *_cachedSearchTerm;
}
- (NSMutableArray *)currentModel {
return _searchController.isActive ? _searchResults : _model;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_searchResults = [[NSMutableArray alloc] init];
_model = [[NSMutableArray alloc] init];
for (int i = 0; i < 10; i++) {
[_model addObject:[NSString stringWithFormat:#"item %d", i]];
}
_searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
_searchController = [[UISearchDisplayController alloc] initWithSearchBar:_searchBar contentsController:self];
_searchController.searchResultsDataSource = self;
_searchController.searchResultsDelegate = self;
_searchController.delegate = self;
[_searchController.searchResultsTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"cell"];
self.tableView.tableHeaderView = _searchBar;
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
controller.searchBar.text = _cachedSearchTerm;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == _searchController.searchResultsTableView) {
_cachedSearchTerm = _searchBar.text;
[_searchController setActive:NO animated:YES];
[self filterResults:_cachedSearchTerm];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[self currentModel] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
cell.textLabel.text = [self currentModel][indexPath.row];
return cell;
}
- (void)filterResults:(NSString *)searchTerm {
[_searchResults removeAllObjects];
[_searchResults addObjectsFromArray:[_model filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF contains[s] %#", searchTerm]]];
[_searchController.searchResultsTableView reloadData];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterResults:searchString];
return YES;
}
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
if (_cachedSearchTerm) {
controller.searchBar.text = _cachedSearchTerm;
}
}
#end
Related
i am displaying list content in table view now i want when i click
one menu of list that menu content display in UIView on next screen
. how to push UITableView to UIView dynamically in iOS.
#import "SmsCategoryTitleTableViewController.h"
#import "CategoryMainWindowViewController.h"
#import "AppDelegate.h"
#import "FMDatabase.h"
#import "FMResultSet.h"
#import "SmsTitle.h"
#import "SMSCategory.h"
#import"smsDisplayViewController.h"
#interface SmsCategoryTitleTableViewController ()
#end
#implementation SmsCategoryTitleTableViewController
#synthesize theSearchBar,Id;
#synthesize theTableView;
#synthesize array;
#synthesize disableViewOverlay;
#synthesize Arrayobject;
- (void)viewDidLoad
{
[super viewDidLoad];
[self SearchBarCode];
[self GetTableData];
[self.tableView reloadData];
filteredContentList = [[NSMutableArray alloc] init];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
// [self performSelector:#selector(push:) withObject:nil afterDelay:0.2f];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
-(void)GetTableData
{
array = [[NSMutableArray alloc] init];
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentDir = [docPaths objectAtIndex:0];
self.databasePath = [documentDir stringByAppendingPathComponent:#"SMS.sqlite"];
FMDatabase *database = [FMDatabase databaseWithPath:self.databasePath];
[database setLogsErrors:TRUE];
[database open];
NSString *anQuery = [[NSString alloc]initWithFormat:#"SELECT * FROM SMSnJokes
where CategoryId=%#",self.Id];
FMResultSet *results = [database executeQuery:anQuery];
while([results next])
{
SmsTitle *title=[[SmsTitle alloc]init];
title.Id = [results stringForColumn:#"Id"];
title.CategoryId = [results stringForColumn:#"CategoryId"];
title.Title = [results stringForColumn:#"Title"];
[array addObject:title];
// NSLog(#"SMS LIST %#",title.Title);
}
[database close];
}
-(void)SearchBarCode
{
self.disableViewOverlay = [[UIView
alloc]initWithFrame:CGRectMake(0.0f,44.0f,320.0f,0)];
self.disableViewOverlay.backgroundColor=[UIColor lightGrayColor];
self.disableViewOverlay.alpha = 0;
theSearchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0, 5, 374.0f, 50)];
theSearchBar.delegate =self;
[self.tableView addSubview:theSearchBar];
self.navigationItem.title=#"SMS LIST";
[[self tableView] setTableHeaderView:theSearchBar];
}
- (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 [array 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 (isSearching)
{
cell.textLabel.text = [filteredContentList objectAtIndex:indexPath.row];
}
else
{
SmsTitle *title = [array objectAtIndex:indexPath.row];
[cell.textLabel setText:[NSString stringWithFormat:#"%# ",[title
valueForKey:#"Title"]]];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (void)searchTableList
{
NSString *searchString =theSearchBar.text;
filteredContentList = [[NSMutableArray alloc]init];
[filteredContentList removeAllObjects];
for (SmsTitle *title in array)
{
NSString *tempStr = title.Title;
NSComparisonResult result = [tempStr compare:searchString options:
(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0,
[searchString length])];
if (result == NSOrderedSame)
{
[filteredContentList addObject:title.Title];
}
}
}
#pragma mark - Search Implementation
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.theSearchBar resignFirstResponder];
}
- (void) dismissKeyboard
{
[self.theSearchBar becomeFirstResponder];
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
isSearching = YES;
[theSearchBar setShowsCancelButton:YES animated: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.tableView reloadData];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
theSearchBar.text=nil;
[theSearchBar setShowsCancelButton:NO animated:YES];
[theSearchBar resignFirstResponder];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[theSearchBar setShowsCancelButton: YES animated: YES];
[self searchTableList];
[searchBar resignFirstResponder];
}
- (void)searchBar:(UISearchBar *)searchBar activate:(BOOL) active
{
self.theTableView.allowsSelection = !active;
self.theTableView.scrollEnabled = !active;
if (!active)
{
[disableViewOverlay removeFromSuperview];
[searchBar resignFirstResponder];
}
else
{
self.disableViewOverlay.alpha = 0;
[self.view addSubview:self.disableViewOverlay];
[UIView beginAnimations:#"FadeIn" context:nil];
[UIView setAnimationDuration:0.5];
self.disableViewOverlay.alpha = 0.6;
[UIView commitAnimations];
NSIndexPath *selected = [self.theTableView indexPathForSelectedRow];
if (selected)
{
[self.theTableView deselectRowAtIndexPath:selected
animated:NO];
}
}
[searchBar setShowsCancelButton:active animated:YES];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
[self.theSearchBar resignFirstResponder];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
textField.returnKeyType=UIReturnKeyDefault ;
return[textField resignFirstResponder];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath
{
smsDisplayViewController *viewController1 = [[smsDisplayViewController alloc]
init];
[self.navigationController pushViewController:viewController1 animated:YES];
}
Ok got your point. I think you want to pass data of selected cell to
next UIViewController. Assume, you want to pass cell title label and
you have an array of objects. In yoursmsDisplayViewController.h
#import <UIKit/UIKit.h>
#interface smsDisplayViewController : UIViewController
#property (strong, nonatomic) NSString *cellName;
Now in your SmsCategoryTitleTableViewController.m you have
NSMutableArray *nameList;
Then in your table view delegate method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
smsDisplayViewController *viewController1 = [self.storyboard instantiateViewControllerWithIdentifier:#"LoginIdentifier"];
viewController1.cellName=[nameList objectAtIndex:indexPath.row];
[self.navigationController pushViewController:viewController1 animated:YES];
}
UPDATE This is the code you posted first in your question.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
smsDisplayViewController *viewController1 = [[smsDisplayViewController
alloc] initWithNibName:#"viewController1" bundle:nil];
[self.navigationController pushViewController:viewController1 animated:YES];
}
Now the wrong thing you are doing here
isinitWithNibName:#"viewController1". If you are not using any nib
file then your code should be
smsDisplayViewController *viewController1 = [[smsDisplayViewController alloc] init];
[self.navigationController pushViewController:viewController1 animated:YES];
You can use Accessory Buttons in UITableView or learn more about segues.
You have to use prepareForSegue: to pass data to another ViewController.
You can learn it from Here which teaches you how to transfer data between ViewControllers while using Segue.
I'm trying to implement a UISearchBar in a custom UITableViewController and done programmatically (not using IB). I got the search function to work and return the correct fields, but it is displaying the searched cells over the full list cells:
As you can see, the new searched field is scrollable and selectable. Its just not removing the old cells.
here is my .h file:
#interface TestTableViewController : UITableViewController <UISearchBarDelegate, UISearchDisplayDelegate>
#property (strong, nonatomic) NSArray *boundaries;
#end
.m file:
#import "TestTableViewController.h"
#import "Boundary.h"
#interface TestTableViewController ()
#property (strong, nonatomic) UISearchDisplayController *searchController;
#property (strong, nonatomic) NSMutableArray *filteredBoundaries;
#end
#implementation TestTableViewController
-(instancetype) initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) {
self.filteredBoundaries = [NSMutableArray array];
}
return self;
}
-(void)viewDidLoad {
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:TRUE selector:#selector(caseInsensitiveCompare:)];
NSArray *sortDescriptors = #[sortDescriptor];
self.boundaries = [self.boundaries sortedArrayUsingDescriptors:sortDescriptors];
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
searchBar.delegate = self;
searchBar.placeholder = #"Search Fields";
searchBar.showsCancelButton = TRUE;
self.tableView.tableHeaderView = searchBar;
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
}
// ------------------------------------------------------------------------------------------------------
#pragma mark -
#pragma mark Setup Filter Data Source
-(void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope {
[self.filteredBoundaries removeAllObjects];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
self.filteredBoundaries = [NSMutableArray arrayWithArray:[self.boundaries filteredArrayUsingPredicate:predicate]];
}
// ------------------------------------------------------------------------------------------------------
#pragma mark -
#pragma mark Table view data source
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.searchDisplayController.searchResultsTableView) {
return self.filteredBoundaries.count;
}
else {
return self.boundaries.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];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
Boundary *boundary = [self.filteredBoundaries objectAtIndex:indexPath.row];
cell.textLabel.text = boundary.name;
cell.textLabel.textColor = [UIColor blackColor];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
}
else {
Boundary *boundary = [self.boundaries objectAtIndex:indexPath.row];
cell.textLabel.text = boundary.name;
cell.textLabel.textColor = [UIColor blackColor];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.userInteractionEnabled = TRUE;
}
return cell;
}
// ------------------------------------------------------------------------------------------------------
#pragma mark -
#pragma mark UISearchDisplayController Delegates
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForSearchText:searchString scope:[[self.searchController.searchBar scopeButtonTitles] objectAtIndex:self.searchController.searchBar.selectedScopeButtonIndex]];
return TRUE;
}
#end
And how I call the table view:
TestTableViewController *tableViewController = [[TestTableViewController alloc] initWithStyle:UITableViewStylePlain];
tableViewController.boundaries = [group.boundaries allObjects];
tableViewController.contentSizeForViewInPopover = POPOVER_SIZE;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tableViewController];
navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
navController.navigationBar.barStyle = UIBarStyleBlack;
self.myPopoverController = [[UIPopoverController alloc] initWithContentViewController:navController];
self.myPopoverController.delegate = self;
[self.myPopoverController presentPopoverFromRect:button.frame inView:button.superview permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Any ideas what I might be doing wrong or missing?
The problem is that UISearchDisplayController is using another UITableView rather than the view controller's own. You can verify that by logging tableView in -tableView:cellForRowAtIndexPath:.
You can use a UISearchBar without a UISearchDisplayController, to have more control over search and display logic.
Also, if your app doesn't support any version prior to iOS 8, consider using UISearchController. I haven't tried it but it seems to give you more control. Check a sample UISearchDisplayControllerhas been deprecated in iOS 8.
Try this
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 41.0)];
[self.view addSubview:searchBar];
searchBar.delegate=self;
- (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 [titlearray count];
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (isSearching)
{
cell.nameLabel.text = [filteredContentList objectAtIndex:indexPath.row];
cell.thumbnailImageView.image =[filteredImgArray objectAtIndex:indexPath.row];
}
else
{
cell.thumbnailImageView.image = [imagearray objectAtIndex:indexPath.row];
cell.nameLabel.text = [titlearray objectAtIndex:indexPath.row];
}
return cell;
}
- (void)searchTableList {
NSString *searchString = searchBar.text;
for (int i=0; i<titlearray.count; i++) {
NSString *tempStr=[titlearray objectAtIndex:i];
NSComparisonResult result = [tempStr compare:searchString options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchString length])];
if (result == NSOrderedSame)
{
[filteredContentList addObject:tempStr];
[filteredImgArray addObject:[imagearray objectAtIndex:i]];
}
}
}
#pragma mark - Search 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];
[filteredImgArray removeAllObjects];
if([searchText length] != 0) {
isSearching = YES;
[self searchTableList];
//tblContentList.hidden=NO;
}
else {
isSearching = NO;
// tblContentList.hidden=YES;
}
[tblContentList reloadData];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Cancel clicked");
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Search Clicked");
[self searchTableList];
}
I hope it's help for you
You should implement correct datasource.
Create new array of items for filtered data for first.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger count = ([filteredItems count] > 0) ? [filteredItems count] : [self.allItems count];
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier: #"id"];
MyCustomItem *item = ([filteredItems count] > 0) ? filteredItems[indexPath.row] : self.allItems[indexPath.row];
[self configureCell:cell forItem:item];
return cell;
}
Configure searching:
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchText = searchController.searchBar.text;
if ([searchText length] == 0)
{
[filteredItems removeAllObjects];
[self.tableView reloadData];
return;
}
NSMutableArray *searchResults = [self.allItems mutableCopy];
// SKIP ALL BODY OF SEARCHING
filteredPeoples = searchResults;
[self.tableView reloadData];
}
Will work pretty.
IOS 8 delegate has been deprecated not sure if that's the problem.
The method
here's [a link]https://developer.apple.com/Library/ios/documentation/UIKit/Reference/UISearchDisplayDelegate_Protocol/index.html#//apple_ref/occ/intfm/UISearchDisplayDelegate/searchDisplayControS 8 delegate has been deprecated not sure if that's the problem.
The method
try this property instead
#property(nonatomic, assign) id< UISearchResultsUpdating > searchResultsUpdater
another better link [a link]https://developer.apple.com/library/ios/samplecode/TableSearch_UISearchController/Listings/TableSearch_obj_c_TableSearch_APLResultsTableController_m.html
Heres a few photos to get started:
This is what I CURRENTLY have for the main view:
Then when the user selects the UISearchBar, this is what happens:
Instead of the second photo, I would like the view to change to this:
Here is the code so far:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
/*
self.searchView = [[UserSearchView alloc] initWithFrame:self.view.frame];
self.searchView.searchResults.delegate = self;
self.searchView.searchResults.dataSource = self;
[self.view addSubview:self.searchView];
*/
self.mainTableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
[self.mainTableView setDelegate:self];
[self.mainTableView setDataSource:self];
[self.mainTableView setShowsHorizontalScrollIndicator:NO];
[self.mainTableView setShowsVerticalScrollIndicator:NO];
[self.view addSubview:self.mainTableView];
self.searchBar = [[UISearchBar alloc] init];
[self.searchBar setBarStyle:UIBarStyleBlackTranslucent];
[self.searchBar setAutocorrectionType:UITextAutocorrectionTypeNo];
[self.searchBar setAutocapitalizationType:UITextAutocapitalizationTypeNone];
self.searchCon = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
[self.searchCon setDelegate:self];
[self.searchCon setSearchResultsDataSource:self];
[self.searchCon setSearchResultsDelegate:self];
self.navigationItem.titleView = self.searchCon.searchBar;
/* This generates the result I want but I do not want the search
* bar in the tableviews header, but rather in the uinavigationcontroller's
* uinavigationbar.
*/
//self.mainTableView.tableHeaderView = self.searchBar;
[self.view setBackgroundColor:[UIColor whiteColor]];
}
#pragma mark -
#pragma mark - UISearchDisplayController Delegate
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
if ([searchString isEqualToString:#""])
return NO;
PFQuery *query = [PFUser query];
[query whereKey:#"username" containsString:searchString];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.array = [NSMutableArray arrayWithArray:objects];
[self.searchDisplayController.searchResultsTableView reloadData];
[self.mainTableView reloadData];
} else {
[[[UIAlertView alloc] initWithTitle:#"Failed Search" message:[NSString stringWithFormat:#"%#", [error userInfo]] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}];
return YES;
}
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller
{
[controller.searchBar setShowsCancelButton:YES animated:YES];
NSLog(#"%#", controller);
}
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
[controller.searchBar setShowsCancelButton:NO animated:YES];
NSLog(#"%#", controller);
}
#pragma mark -
#pragma mark - UITableView Delegate & Datasource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
}
[cell.textLabel setText:[[self.array objectAtIndex:[indexPath row]] objectForKey:#"username"]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ProfileViewController *profile = [[ProfileViewController alloc] init];
[profile setProfileUser:[self.array objectAtIndex:[indexPath row]]];
[self.navigationController pushViewController:profile animated:YES];
}
I am kinda lost on how to make the destination view work. Viewing the Facebook application is something I would like to reproduce, the way their search bars are implemented.
In addition, I'm using the PARSE framework. So a lot of the data being populated into the tableview is abstracted from the code.
Try this...
In your .h file
#interface YourtViewController : UIViewController <UITableViewDataSource,UITableViewDelegate,UISearchBarDelegate,UISearchDisplayDelegate>
#property (nonatomic,strong) UISearchDisplayController* searchDisplayController;
#property (weak, nonatomic) IBOutlet UISearchBar *mySearchBar; //connect this IBOutlet to your serach bar in your storyboard or xib.
In your viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
self.mySearchBar.delegate=self;
self.searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:self.mySearchBar contentsController:self];
self.searchDisplayController.delegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.searchResultsDelegate = self;
// do your additional code here
//
}
Now implement delegate methods of searchDisplayController.
I am pretty new in objective c so hopefully this all make sense.I have followed this video tutorial from YouTube.The program is not working .
You can download the project from this link.Guide me
to make this program functional.
use the following tutorial is the simple way to get the answer and and also u get the sample code in github, the link is http://www.appcoda.com/how-to-add-search-bar-uitableview/
in your view controller.h file
import
#interface RecipeBookViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
NSArray *recipes; //this is used for load the data to table
NSArray *searchResults; //this is used for search the particular name in uitableview
}
#property (nonatomic, strong) UITableView *tableView; //progrmatically allocationg the tableview
.m file
#synthesize tableView; //this is used accessing the name in more than one time
- (void)viewDidLoad
{
[super viewDidLoad];
// Initialize table data
searchResults=[NSArray alloc]init];
recipes = [NSArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto", #"Full Breakfast", #"Hamburger", #"Green Tea", #"Thai Shrimp Cake", #"Angry Birds Cake", #"Ham and Cheese Panini", nil];
//create the tableview
tableView =[[UITableView alloc]initWithFrame:CGRectMake(0, 163, 320, 317)];
tableView.delegate=self;
tableView.dataSource=self;
[self. tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"cell"];
[self.view addSubview: tableView];
}
//this is for loading the table data
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return [recipes count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
}
return cell;
}
//this is for search bar delegate method for filtering
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}
#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;
}
finally add the one search bar display controller only in top on the view
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar; // called when text starts editing
{
if (searching)
{
searching=YES;
letsUserSelectRow=YES;
}
else
{
searching=NO;
letsUserSelectRow=YES;
}
// self.tbl_searchtable.scrollEnabled=NO;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar
{
searching = NO;
letsUserSelectRow = YES;
searchBar.text = #"";
[searchBar resignFirstResponder];
[self.tbl_searchuser reloadData];
}
-(NSIndexPath *)tableView :(UITableView *)theTableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(letsUserSelectRow)
return indexPath;
else
return nil;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText; // called when text changes (including clear)
{
_tbl_searchuser.hidden=FALSE;
[copylistofitem removeAllObjects];
if([searchText length] > 0)
{
searching = YES;
letsUserSelectRow = YES;
self.tbl_searchuser.scrollEnabled = YES;
[self searchtableview];
}
else
{
searching = NO;
letsUserSelectRow= NO;
[_searchbar resignFirstResponder];
//self.tbl_searchtable.scrollEnabled = NO;
}
[copylistofitem retain];
[self.tbl_searchuser reloadData];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar; // called when keyboard search button pressed
{
[self hide];
//[self searchtableview];
}
-(void)searchtableview
{
_tbl_searchuser.frame=CGRectMake(0, 65, 320, 140);
NSString *searchText = _searchbar.text;
NSLog(#"%#",array_allusers);
for(int l = 0; l < [array_allusers count]; l++)
{
NSString *tempstr = [[array_allusers objectAtIndex:l] objectForKey:#"username"];
NSRange rngstr = [tempstr rangeOfString:searchText options:(NSAnchoredSearch | NSCaseInsensitiveSearch)];
if(rngstr.length > 0)
{
[copylistofitem addObject:[array_allusers objectAtIndex:l]];
[copylistofitem retain];
}
}
NSLog(#"%#",copylistofitem);
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"username" ascending:YES];
[copylistofitem sortUsingDescriptors:[NSArray arrayWithObject:sort]];
[_tbl_searchuser reloadData];
}
-(void)hide
{
[_searchbar resignFirstResponder];
_tbl_searchuser.frame=CGRectMake(0, 65, 320, 274);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (searching && [_searchbar.text length] > 0)
return [copylistofitem count];
else
return yourarray;
}
NSMutableArray *copylistofitem;
BOOL searching;
BOOL letsUserSelectRow;
I create a UIViewController with a UITableView and UISearchDisplayController, the problem is that shouldReloadTableForSearchString not run...this is my code, where is the mistake for you?
- (void)viewDidLoad {
[super viewDidLoad];
array = [[NSMutableArray alloc] initWithObjects:#"ciao",#"mandi",#"viva",#"blabla", nil];
arrayFiltrato = [[NSMutableArray alloc] initWithObjects:#"ciao",#"mandi",#"viva",#"blabla", nil];
//[self.tableView setContentOffset:CGPointMake(0, 44.f) animated:NO];
[self.tableView reloadData];
[self setSearchBar];
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
[self.navigationController setNavigationBarHidden: NO];
}
- (void) setSearchBar {
self.searchBar = [[UISearchBar alloc] init];
[self.searchBar setAutocapitalizationType:UITextAutocapitalizationTypeNone];
[self.searchBar setPlaceholder:#"Type a search term" ];
[self.searchBar setTintColor:[UIColor blackColor]];
[self.searchBar setDelegate:self];
[self.searchBar sizeToFit];
[self.tableView setTableHeaderView:self.searchBar];
self.searchDisplay = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
[self.searchDisplay setSearchResultsDataSource:self];
[self.searchDisplay setSearchResultsDelegate:self];
[self.searchDisplay setDelegate:self];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)myTableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)myTableView numberOfRowsInSection:(NSInteger)section {
if (myTableView == self.tableView) {
return array.count;
}
else{
return arrayFiltrato.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)myTableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if (myTableView == self.tableView) {
cell.textLabel.text = [array objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [arrayFiltrato objectAtIndex:indexPath.row];
}
return cell;
}
#pragma mark -
#pragma mark Content Filtering
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{
[arrayFiltrato removeAllObjects];
// if ([scope isEqualToString:#"All"] || [product.type isEqualToString:scope]) {
for (NSString *str in array) {
NSLog(#"str: %# - scope: %#",str,scope);
if ([scope isEqualToString:str]) {
NSComparisonResult result = [str compare:searchText
options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)
range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame) {
[arrayFiltrato addObject:str];
}
}
}
}
#pragma mark -
#pragma mark UIsearchDisplay Delegate Methods
- (BOOL)searchDisplay:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
NSLog(#"ok");
return YES;
}
- (BOOL)searchDisplay:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption{
NSLog(#"ok");
[self filterContentForSearchText:[self.searchDisplayController.searchBar text]
scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
return YES;
}
- (void)searchDisplayDidBeginSearch:(UISearchDisplayController *)controller{
[self.searchDisplayController.searchResultsTableView setDelegate:self];
}
- (void)searchDisplayDidEndSearch:(UISearchDisplayController *)controller{
//[self.tableView setContentOffset:CGPointMake(0, 44.f) animated:YES];
}
#pragma mark -
-(void)searchBar:(id)sender{
[self.searchDisplayController setActive:YES animated:YES];
}
The problem is that the delegate method is wrong, isn't this:
- (BOOL)searchDisplay:(UISearchDisplayController *)controller shouldRelo....
but this:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldRelo...