Grabbing UISearchBar data - Objective C - ios

I've created a UISearchBar in one of my ViewControllers that contain different containers that link to other ViewControllers. This UISearchBar is in the parent ViewController. I am trying to grab the text that was entered in the search bar to be used to send to another ViewController The UISearchBar was created in StoryBoard. I am using the following methods to try and receive information from the Search Bar:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
NSLog(#"searching");
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSLog(#"Text change");
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Cancel clicked");
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Search Clicked");
}
Non of these functions above seem to run, I am not sure why. Suggestions or thoughts?
UPDATE:
Here is what I am using to initiate the Search Bar now:
_aSearchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
[_aSearchBar sizeToFit];
_aSearchBar.delegate = self;
_aSearchBar.placeholder = #"Search YouTube...";
_searchDC = [[UISearchDisplayController alloc] initWithSearchBar:_aSearchBar contentsController:self];
[self performSelector:#selector(setSearchDisplayController:) withObject:_searchDC];
_searchDC.delegate = self;
_searchDC.searchResultsDataSource = self;
_searchDC.searchResultsDelegate = self;
[_aSearchBar release];
NSLog(#"%#",[_searchDC.delegate class]); <------ this prints home which is the correct class
Now the only issue is, I can't see the search bar anymore?

If the delegate methods are not being called it means that the UISearchBar doesn't know where to delegate the optional methods in UISearchBarDelegate protocol.
So the ViewController that implements these methods
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
NSLog(#"searching");
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSLog(#"Text change");
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Cancel clicked");
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Search Clicked");
}
must be set as the delegate of the UISearchBar. To make sure that the correct ViewController is set as the delegate of the UISearchBar I would print the
[searchBar.delegate class]
If this returns nil or some other class name then the one you expect, you will know where the problems comes from.
Hope this helps.
UPDATE
Ok, I just created a Single View Application and dragged a UISearchBar on the storyboard. Then I added an outlet for the UISearchBar called searchBar. Then I made the ViewController implement the UISearchBarDelegate protocol. Then in ViewDidLoad I set the searchBar.delegate = self. After I added all the delegate methods listed above everything worked... So the only thing that I can think of now is that the ViewController is not implementing the protocol
#interface ViewController () <UISearchBarDelegate>
Here's the ViewController source code:
#import "ViewController.h"
#interface ViewController () <UISearchBarDelegate>
#property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.searchBar.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UISearchBarDelegate
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
NSLog(#"searching");
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSLog(#"Text change");
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Cancel clicked");
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Search Clicked");
}

Related

UISearchBar - ReturnKeyType not working for iOS 8

I am using UISearchbar in tableview controller in storyboard.
And searchbar returnKeyType is UIReturnKeySearch.
Its working fine with iOS7 but returnKeyType is not working with iOS8.
in iOS8, return key appears every time in keyboard.
I tried to set returnkeytype in viewDidLoad method of controller too.
What I need to do to set returnKeyType = UIReturnKeySearch in iOS8?
I think you can go with your hard codded logic for right now.
I will update if I will get better solution for your problem.
-(void)viewDidLoad {
[self setReturnKeyTypeSearchForView:searchBar];
}
-(void)setReturnKeyTypeSearchForView:(UIView *)view
{
for (id subView in view.subviews) {
if ([subView isKindOfClass:[UITextField class]]) {
[subView setReturnKeyType:UIReturnKeySearch];
}
else {
[self setReturnKeyTypeSearchForView:subView];
}
}
if ([view isKindOfClass:[UITextField class]]) {
[(UITextField *)view setReturnKeyType:UIReturnKeySearch];
}
}
Try making IBOutlet of your SearchBar
#property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
and add the below line code to your viewDidLoad Method
// if u want Done return key and change accordingly.
_searchBar.returnKeyType = UIReturnKeyDone;
SearchViewController.h
//
#import <UIKit/UIKit.h>
#interface SearchViewController : UIViewController
<UISearchBarDelegate, UITableViewDataSource> {
NSMutableArray *tableData;
UIView *disableViewOverlay;
UITableView *theTableView;
UISearchBar *theSearchBar;
}
#property(retain) NSMutableArray *tableData;
#property(retain) UIView *disableViewOverlay;
#property (nonatomic, retain) IBOutlet UITableView *theTableView;
#property (nonatomic, retain) IBOutlet UISearchBar *theSearchBar;
- (void)searchBar:(UISearchBar *)searchBar activate:(BOOL) active;
#end
SearchViewController.m
//
#import "SearchViewController.h"
#implementation SearchViewController
#synthesize tableData;
#synthesize disableViewOverlay;
#synthesize theSearchBar;
#synthesize theTableView;
// Initialize tableData and disabledViewOverlay
- (void)viewDidLoad {
[super viewDidLoad];
self.tableData =[[NSMutableArray alloc]init];
self.disableViewOverlay = [[UIView alloc]
initWithFrame:CGRectMake(0.0f,44.0f,320.0f,416.0f)];
self.disableViewOverlay.backgroundColor=[UIColor blackColor];
self.disableViewOverlay.alpha = 0;
}
// Since this view is only for searching give the UISearchBar
// focus right away
- (void)viewDidAppear:(BOOL)animated {
[self.theSearchBar becomeFirstResponder];
[super viewDidAppear:animated];
}
#pragma mark -
#pragma mark UISearchBarDelegate Methods
- (void)searchBar:(UISearchBar *)searchBar
textDidChange:(NSString *)searchText {
// We don't want to do anything until the user clicks
// the 'Search' button.
// If you wanted to display results as the user types
// you would do that here.
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
// searchBarTextDidBeginEditing is called whenever
// focus is given to the UISearchBar
// call our activate method so that we can do some
// additional things when the UISearchBar shows.
[self searchBar:searchBar activate:YES];
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
// searchBarTextDidEndEditing is fired whenever the
// UISearchBar loses focus
// We don't need to do anything here.
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
// Clear the search text
// Deactivate the UISearchBar
searchBar.text=#"";
[self searchBar:searchBar activate:NO];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
// Do the search and show the results in tableview
// Deactivate the UISearchBar
// You'll probably want to do this on another thread
// SomeService is just a dummy class representing some
// api that you are using to do the search
NSArray *results = [SomeService doSearch:searchBar.text];
[self searchBar:searchBar activate:NO];
[self.tableData removeAllObjects];
[self.tableData addObjectsFromArray:results];
[self.theTableView reloadData];
}
// We call this when we want to activate/deactivate the UISearchBar
// Depending on active (YES/NO) we disable/enable selection and
// scrolling on the UITableView
// Show/Hide the UISearchBar Cancel button
// Fade the screen In/Out with the disableViewOverlay and
// simple Animations
- (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];
// probably not needed if you have a details view since you
// will go there on selection
NSIndexPath *selected = [self.theTableView
indexPathForSelectedRow];
if (selected) {
[self.theTableView deselectRowAtIndexPath:selected
animated:NO];
}
}
[searchBar setShowsCancelButton:active animated:YES];
}
#pragma mark -
#pragma mark UITableViewDataSource Methods
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"SearchResult";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
id *data = [self.tableData objectAtIndex:indexPath.row];
cell.textLabel.text = data.name;
return cell;
}
#pragma mark -
#pragma mark Memory Management Methods
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[theTableView release], theTableView = nil;
[theSearchBar release], theSearchBar = nil;
[tableData dealloc];
[disableViewOverlay dealloc];
[super dealloc];
}
#end
Building a SearchView with UISearchBar and UITableView
this might helps you :)
I'm not sure if I understood your question correctly. You want to have "search" button instead of "return" button, right? There is a new SearchController in ios 8, give it a try:
YourTableViewController.h
#interface YourTableViewController : UITableViewController<UISearchResultsUpdating>
#end
And now the implementation:
YourTableViewController.m
- (void)viewDidLoad {
// initializing with the same controller as presenting
UISearchController *searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
searchController.searchResultsUpdater = self;
searchController.searchBar.frame = CGRectMake(searchController.searchBar.frame.origin.x, searchController.searchBar.frame.origin.y, searchController.searchBar.frame.size.width, 44.0f);
searchController.dimsBackgroundDuringPresentation = NO;
searchController.searchBar.delegate = self;
searchController.searchBar.returnKeyType = UIReturnKeySearch; //should be search by default.. you can change to whatever you want.
// adding searchBar into HeaderView
self.tableView.tableHeaderView = searchController.searchBar;
// just to be able to present results on the same controller
self.definesPresentationContext = YES;
}
You also have to implement method from UISearchResultsUpdating protocol:
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
// you can leave it blank
}
EDIT: If it is not what you were looking for please comment, so I can update my answer accordingly
try this in viewDidLoad:
UITextField *txfSearchField = [yourSearchbar valueForKey:#"_searchField"];
if([txfSearchField conformsToProtocol:#protocol(UITextInputTraits)]) {
[txfSearchField setReturnKeyType:UIReturnKeyDefault];
}

Getting -[SearchViewController tableView:numberOfRowsInSection:]: unrecognized selector sent to instance

The following is the code for a View Controller in which I'm adding a Search bar and performing things:
SearchViewController.h
#import <UIKit/UIKit.h>
#interface SearchViewController : UIViewController <UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UISearchBar *search;
#end
SearchViewController.m
#import "SearchViewController.h"
#import "MMDrawerController/UIViewController+MMDrawerController.h"
#interface SearchViewController ()
#end
#implementation SearchViewController
#synthesize search;
- (BOOL)prefersStatusBarHidden
{
return YES;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[search.delegate self];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
[search setShowsCancelButton:YES animated:NO];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITextFieldMethod
-(void) textFieldDidEndEditing:(UITextField *)textField
{
[search resignFirstResponder];
}
-(BOOL) textFieldShouldReturn:(UITextField *)textField
{
[search resignFirstResponder];
return YES;
}
#pragma mark - HandlingKeyboard
-(void) dismissKeyboard
{
[search resignFirstResponder];
}
#pragma mark - UISearchBarMethods
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[search resignFirstResponder];
[search endEditing:YES];
[self.mm_drawerController toggleDrawerSide:MMDrawerSideRight animated:YES completion:nil];
}
- (void) searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
[search resignFirstResponder];
[self.mm_drawerController toggleDrawerSide:MMDrawerSideRight animated:YES completion:nil];
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
[search resignFirstResponder];
}
#end
While clicking in the search bar to enter text, I'm getting an error of:
-[SearchViewController tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x8e68990
From error it looks like that your app try too find table view delegate methods. Couple of check
Can you remove code for
"MMDrawerController/UIViewController+MMDrawerController.h" and try?
Does your nib file contain table view? If yes can you check if its
connected to any IBOutlets or not?

When cancel button of searchBar is clicked, it should remove the keyboard from the screen

I am using a searchBar wherein the cancel button of searchBar when clicked should remove the keyboard. I tried using resignFirstResponder but thats not working at all. Does anyone have any other way out for it?
use this line, it will help you
[self.view endEditing:YES];
Without any code in OP, try this:
[self.view endEditing:YES];
You'll need one/all of these methods:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (searchText.length == 0) {
[searchBar resignFirstResponder];
}
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
}
this test code it work 1000%.
In your .h file
#interface ViewController : UIViewController<UISearchBarDelegate>
set delegate in your viewDidLoad method
#property (strong, nonatomic) UISearchBar *searchBar;
- (void)viewDidLoad
{
[super viewDidLoad];
[self.searchBar setDelegate:self];
}
-(BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar{
[self.searchBar setShowsCancelButton:YES];
return YES;
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
searchBar.text = #"";
[searchBar resignFirstResponder];
}

UISearchBar in a UICollectionView disappears when using UISearchDisplayController

I have a UISearchBar added as a subview to a UICollectionView, and attached to a UISearchDisplayController.
I set it up in viewDidLoad:
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar
contentsController:self];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
[self.collectionView addSubview:self.searchBar];
When I push another view controller to the navigation controller then pop it, the search bar disappears. This only happens if the collection view is scrolled down enough for the search bar to be hidden. Also, even though the search bar disappears, tapping the white space where it's supposed to be activates the search display controller attached to it.
This happens only on iOS 7, and if I remove the search display controller the search bar will not disappear.
One more thing worth mentioning. When the search bar has disappeared, if I push another view controller then pop it, the bar will be visible again.
Apparently this is a bug of UISearchDisplayController on iOS 7, so any ideas on how to work around it?
I ended up implementing UISearchDisplayController on my own. Here's my code.
ZBNSearchDisplayController.h
#protocol ZBNSearchDisplayDelegate;
#interface ZBNSearchDisplayController : NSObject<UISearchBarDelegate>
- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController;
- (void)setActive:(BOOL)visible animated:(BOOL)animated;
#property(nonatomic,assign) id<ZBNSearchDisplayDelegate> delegate;
#property(nonatomic, getter = isActive) BOOL active;
#property(nonatomic, readonly) UISearchBar *searchBar;
#property(nonatomic, readonly) UIViewController *searchContentsController;
#property(nonatomic, readonly) UITableView *searchResultsTableView;
#property(nonatomic, assign) id<UITableViewDataSource> searchResultsDataSource;
#property(nonatomic, assign) id<UITableViewDelegate> searchResultsDelegate;
#end
#protocol ZBNSearchDisplayDelegate <NSObject>
#optional
- (void)searchDisplayControllerWillBeginSearch:(ZBNSearchDisplayController *)controller;
- (void)searchDisplayControllerDidBeginSearch:(ZBNSearchDisplayController *)controller;
- (void)searchDisplayControllerWillEndSearch:(ZBNSearchDisplayController *)controller;
- (void)searchDisplayControllerDidEndSearch:(ZBNSearchDisplayController *)controller;
- (void)textDidChange:(NSString *)searchText;
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope;
#end
ZBNSearchDisplayController.m
#import "ZBNSearchDisplayController.h"
#implementation ZBNSearchDisplayController
- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController {
self = [super init];
if (self) {
_searchBar = searchBar;
_searchBar.delegate = self;
_searchContentsController = viewController;
CGFloat y = 64.0f;
CGFloat height = _searchContentsController.view.frame.size.height - y;
_searchResultsTableView = [[UITableView alloc] initWithFrame:CGRectMake(0.0f, y, _searchContentsController.view.frame.size.width, height)];
_searchResultsTableView.scrollsToTop = NO;
}
return self;
}
- (void)setSearchResultsDataSource:(id<UITableViewDataSource>)searchResultsDataSource {
_searchResultsTableView.dataSource = searchResultsDataSource;
}
- (void)setSearchResultsDelegate:(id<UITableViewDelegate>)searchResultsDelegate {
_searchResultsTableView.delegate = searchResultsDelegate;
}
- (void)setActive:(BOOL)visible animated:(BOOL)animated {
if (!visible) {
[_searchBar resignFirstResponder];
_searchBar.text = nil;
_searchBar.showsCancelButton = NO;
}
if (visible && [self.delegate respondsToSelector:#selector(searchDisplayControllerWillBeginSearch:)]) {
[self.delegate searchDisplayControllerWillBeginSearch:self];
} else if (!visible && [self.delegate respondsToSelector:#selector(searchDisplayControllerWillEndSearch:)]) {
[self.delegate searchDisplayControllerWillEndSearch:self];
}
[_searchContentsController.navigationController setNavigationBarHidden:visible animated:YES];
float alpha = 0;
if (visible) {
[_searchContentsController.view addSubview:_searchResultsTableView];
alpha = 1.0;
}
if ([_searchContentsController.view respondsToSelector:#selector(scrollEnabled)]) {
((UIScrollView *)_searchContentsController.view).scrollEnabled = !visible;
}
if (animated) {
[UIView animateWithDuration:0.2 animations:^{
_searchResultsTableView.alpha = alpha;
} completion:^(BOOL finished) {
self.active = visible;
}];
} else {
_searchResultsTableView.alpha = alpha;
}
}
#pragma mark - UISearchBarDelegate
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope {
if ([self.delegate respondsToSelector:#selector(searchBar:selectedScopeButtonIndexDidChange:)]) {
[self.delegate searchBar:searchBar selectedScopeButtonIndexDidChange:selectedScope];
}
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if ([self.delegate respondsToSelector:#selector(textDidChange:)]) {
[self.delegate textDidChange:searchText];
}
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:YES animated:YES];
[self setActive:YES animated:YES];
[_searchResultsTableView reloadData];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[_searchResultsTableView reloadData];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self setActive:NO animated:YES];
[self.searchResultsTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
}
#end

Insert UITextField above a table view

I have a regular TableViewController and want to add a UITextField above that will populate the TableView data. How I can programmatically place right above the cells?
Thanks
You could place the UITextField in the UITableViewController's header.
Use the UITableViewController Delegate methods to set the properties of the header.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
Alternatively, you could use a UISearchBar.
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 0)];
searchBar.delegate = self;
[searchBar sizeToFit];
tableView.tableHeaderView = searchBar;
Then, in the UISearchBar delegate methods.
#pragma mark - UISearchBar Delegate Methods
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
// Remove the keyboard
[searchBar endEditing:YES];
// This method filters the data based on the search text.
[self filterDataUsingSearchText:searchBar.text];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
// Remove the keyboard
[searchBar endEditing:YES];
// Clear the text on cancel
searchBar.text = #"";
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
// This method filters the data based on the search text.
[self filterDataUsingSearchText:searchText];
}
#pragma mark -
Documentation:
UISearchBar Reference
Table View Programming Guide

Resources