Can't change UITableView frame in searchBar methods - ios

I have a view controller which is fully occupied by a UINavigationBar and UITableView. When the user taps the search bar in the UITableView, I want to hide the navigation bar and allow the table view to fully occupy the screen. Here's my code:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSLog(#"typing text");
navBar.hidden = YES;
[tableview setFrame:CGRectMake(0, 20, 320, 568)];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
NSLog(#"clearing text");
navBar.hidden = NO;
[tableview setFrame:CGRectMake(0, 64, 320, 504)];
}
However, the appearance/frame change code is not working. On the other hand, I know these methods are being called because the NSLogs show up. Can anyone offer any solution?

Try this instead:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSLog(#"typing text");
[self.navigationController setNavigationBarHidden:YES animated:YES];
[self.tableView setFrame:CGRectMake(0, 20, 320, 568)];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
NSLog(#"clearing text");
[self.navigationController setNavigationBarHidden:NO animated:YES];
[self.tableView setFrame:CGRectMake(0, 64, 320, 504)];
}
There is something about adding the animation flag that corrects the problem. Hope this helps!

You should use search display controller (UISearchDisplayController class) for the search functionality.
A search display controller manages display of a search bar and a table view that displays the results of a search of data. I believe it also comes with the functionality you are attempting to create above.
This guide is helpful: http://www.appcoda.com/search-bar-tutorial-ios7/

Related

SearchDisplayController's searchResultsTableView not showing

I'm adding a search bar to the titleView of the navigationItem, so that it looks like this.
But when I tap on the search bar to get focus, it moves out of the screen and the keyboard is dismissed automatically, and then it looks like this.
So, I'm neither able to type anything, nor see any results.
Here is my code where I am adding the search bar to the navigation item in viewDidLoad method.
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0.0, 320.0, 44.0)];
self.searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
UIView *searchBarView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 310.0, 44.0)];
[self.searchBar setShowsCancelButton:NO animated:NO];
searchBarView.autoresizingMask = 0;
self.headSearchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.headSearchDisplayController.delegate = self;
self.headSearchDisplayController.searchResultsDelegate = self;
self.headSearchDisplayController.searchResultsDataSource = self;
[searchBarView addSubview:self.searchBar];
self.searchBar.delegate = self;
self.navigationItem.titleView =searchBarView;
I tried it without setting the autoresizingmask, without any success. I am getting a hint that this behavior is happening because the search bar is in a view which is 44points, which is again inside the titleView. I am guessing that the searchResultsTableView doesn't have enough height to be seen, and thus we're only able to see the overlay. How do I solve this issue? Pointers in the right direction will be extremely helpful.
Here is an animated gif of the situation.
I figured out that the Navigation bar was usually pushed up, when the search was focused, and since the search bar was in the navigation bar it was pushed up with it, and couldn't be visible on the screen.
I solved this by subclassing the UISearchDisplayController to hide the navigationBar. Here is the code.
#import "CustomSearchDisplayController.h"
#implementation CustomSearchDisplayController
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
if(self.active == visible) return;
[self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
if (visible) {
[self.searchBar becomeFirstResponder];
} else {
[self.searchBar resignFirstResponder];
}
}
#end
Found this answer here: https://stackoverflow.com/a/3257456/1011042

Display UISearchBar over tableView when user touches UIBarButtonItem

In my iOS app, I would like to have a right side search button in my UINavigationController, and when a user touches the button, the UISearchBar above my UITableView is shown.
I would like the UISearchBar hidden when the view loads, and then hidden again when the user clicks the Cancel button in the UISearchDisplayController.
I've searched everywhere and cannot find an example. Help?
There is a nice sample project here. The key points are:
1.Hide the Search Bar before presenting the View:
-(void)viewWillAppear:(BOOL)animated {
[self hideSearchBar];
}
-(void)hideSearchBar {
CGRect newBounds = self.tableView.bounds;
newBounds.origin.y = newBounds.origin.y + self.searchBar.bounds.size.height;
self.tableView.bounds = newBounds;
}
2.On the action target for your search button, display the Search Bar
// make the search bar visible
// code example from https://github.com/versluis/Table-Seach-2013 to deal with iOS 7 behavior
-(IBAction)displaySearchBar:(id)sender {
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
NSTimeInterval delay;
if (self.tableView.contentOffset.y >1000) delay = 0.4;
else delay = 0.1;
[self performSelector:#selector(activateSearch) withObject:nil afterDelay:delay];
}
- (void)activateSearch
{
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
[self.searchBar becomeFirstResponder];
}
3.Finally, hide the SearchBar when Cancel is clicked
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self hideSearchBar];
}

Hide UISearchBar until user scrolls?

I implemented a search bar and search display controller on top of my table view.
When the view loads the search bar and relative scopes are always visible.
Is there a simple way to hide it until the user scrolls down, like it happens in the Music app?
You need to add search bar as a header of the table view and then set the contentoffset property of table view in viewDidLoad as,
[self.tableView setContentOffset:CGPointMake(0,44) animated:YES];//or (0, 88) depends on the height of it
For search display controller, you can try this as well,
[self.searchDisplayController setActive:NO animated:YES];
another approach without hardcode
[self.tableView setContentOffset:CGPointMake(0.0, self.tableView.tableHeaderView.frame.size.height) animated:YES];
After a few hours of hair pulling, something that works
on iOS 9
doesn't depend on the number of rows in the table
with variable height rows
Considering the searchbar is the tableView.tableHeaderView
#interface MyTableViewController ()
#property (nonatomic, assign) BOOL firstLayout;
#end
- (void) viewDidLoad {
[super viewDidLoad];
self.firstLayout = YES;
//your code
}
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
if(self.firstLayout){
CGPoint offset = CGPointMake(0, self.tableView.tableHeaderView.frame.size.height - self.tableView.contentInset.top);
[self.tableView setContentOffset:offset];
self.firstLayout = NO;
}
}
for iOS 7 and using UINavigationController
[self.tableView setContentOffset:CGPointMake(0, self.searchBar.height + self.navigationController.navigationBar.height)];
Best way i did reload tableview in
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
[self performSelector:#selector(reload:) withObject:nil afterDelay:0.0];
self.edgesForExtendedLayout = UIRectEdgeNone;
}
- (void)reload:(__unused id)sender {
[self.searchDisplayController setActive:YES];
[self.tableView reloadData];
[self.refreshControl endRefreshing];
} else {
[self.refreshControl endRefreshing];
[[[UIAlertView alloc]initWithTitle:#"Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil] show];
}
}
Thanks
This works fine on iOS9+
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_main_queue(), ^{
self.tableView.contentOffset = CGPointMake(0, -20);
});
}

Adding a toolbar to the result of an UISearchDisplayController

i´m having a tough time with UISearchDisplayController. In my scenario i have an UIView pushed onto a navgation controller. In the UIView i have an UITableView and UIToolbar. In the UITableView I´m using UISearchDisplayController.
The toolbar buttons are used to add additional filter options to the search. My problem is that I can´t figure out, how to add the toolbar at the bottom of the result table view of the UISearchDisplayController.
What is the way to go to add a toolbar to the results?
I finally managed to solve my problem.
Instead of using UISearchDisplayController i only add a UISearchBar to my UITableView and replicate the behavior of UISearchDisplayController with the UISearchBarDelegate methods.
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[self setSearchText:searchText];
[self filterCards];
}
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope
{
[self setScopeIndex:selectedScope];
[self filterCards];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
// Move searchbar to table view
[self.chapterSearchBar removeFromSuperview];
[self.chapterTableView addSubview:[self chapterSearchBar]];
// Show navigation controller
[self.navigationController setNavigationBarHidden:NO animated:YES];
// Hide scope bar an resize
[searchBar setShowsScopeBar:NO];
[searchBar sizeToFit];
// Hide cancel button
[searchBar setShowsCancelButton:NO animated:YES];
// Resize table view
CGRect tableViewRect = [self.chapterTableView frame];
tableViewRect.origin.y = 0;
[self.chapterTableView setFrame:tableViewRect];
// Hide keyboard
[searchBar resignFirstResponder];
[self setSearchText:#""];
[self filterCards];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
// Move searchbar to controller view
[self.chapterSearchBar removeFromSuperview];
[self.view addSubview:[self chapterSearchBar]];
// Hide navigation controller
[self.navigationController setNavigationBarHidden:YES animated:YES];
// Show scope bar an resize
[searchBar setShowsScopeBar:YES];
[searchBar sizeToFit];
// Show cancel button
[searchBar setShowsCancelButton:YES animated:YES];
// Resize table view
CGRect tableViewRect = [self.chapterTableView frame];
tableViewRect.origin.y = 44;
[self.chapterTableView setFrame:tableViewRect];
return YES;
}
If anyone's curious how to solve this issue with still using UISearchDisplayController (cleaner probably), simply set the items of your toolbar to your view controller's toolbarItems while search is active:
self.navigationController.toolbarHidden = NO;
self.toolbarItems = optionsToolbar.items;
The UISearchDisplayController retains the view controller's toolbar according to toolbarItems, so this might already be done for you. Can be useful if the toolbar is only being used during search.

Using a Search Bar through an sqlite database

I am building an iPhone application loading data from SQLite database. Until now I have managed to deal with it as it should, but now i need to add a search bar on top to search through the database content dynamically and obtain the proper search results.
I am using Xcode 4.3.3 , and I am a newb in Xcoding.
I have seen almost every tutorial ever posted online and i need some help.
Anyone have any very specific tutorial or sample code that could help? It will be highly appreciated.
Everyone this is the most helpful link ever found
http://code-ninja.org/blog/2012/01/08/ios-quick-tip-filtering-a-uitableview-with-a-search-bar/
You could use an NSPredicate.
http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/Reference/NSPredicate.html
[NSPredicate predicateWithFormat:#"whatYouAreSearching LIKE %#", searchBar.text];
If you're using an NSFetchRequest, you can assign it a predicate using it's setPredicate method.
Your controller must implement UISearchBarDelegate protocol
then in init method, add this or similar
CGRect searchBarRect = CGRectMake(0, 0, self.view.bounds.size.width, 44);
_searchBar = [[UISearchBar alloc] initWithFrame:searchBarRect];
_searchBar.delegate = self;
after that, implement these three methods, I will post something that looks like mine implementations
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:YES animated:YES];
self.tableView.allowsSelection = NO;
self.tableView.scrollEnabled = NO;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
searchBar.text=#"";
[searchBar setShowsCancelButton:NO animated:YES];
[searchBar resignFirstResponder];
self.tableView.allowsSelection = YES;
self.tableView.scrollEnabled = YES;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:NO animated:YES];
[searchBar resignFirstResponder];
self.tableView.allowsSelection = YES;
self.tableView.scrollEnabled = YES;
/* fire method that does querying with searchBar.text as attribute */
[self some method:searchBar.text];
}

Resources