Has anyone been successful implementing a UIViewController that contais both a UISearchController searchBar and a UItableView while laying everything out using Auto Layout?
I'm trying to achieve something similar to what 1Password does on the iPhone: a fixed searchBar on top of a tableView (not part of its tableHeaderView). When the UISearchController that owns the searchBar gets activated, its searchBar animates to show the scope buttons and thus the tableView moves down a bit.
I have got the basics of this layout working correctly with this class:
//
// ViewController.m
// UISearchControllerIssues
//
// Created by Aloha Silver on 05/02/16.
// Copyright © 2016 ABC. All rights reserved.
//
#import "ViewController.h"
#interface ViewController () <UISearchResultsUpdating, UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) UITableView *tableView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupTableView];
[self setupSearchInterface];
[self setupConstraints];
self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = YES;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.searchController.searchBar sizeToFit];
}
- (void)setupTableView {
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.tableView];
}
- (void)setupSearchInterface {
self.definesPresentationContext = YES;
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.searchController.searchBar.scopeButtonTitles = #[#"One", #"Two"];
self.searchController.searchBar.translatesAutoresizingMaskIntoConstraints = NO;
self.searchController.searchResultsUpdater = self;
[self.view addSubview:self.searchController.searchBar];
}
- (void)setupConstraints {
NSDictionary *layoutViews = #{#"searchBar": self.searchController.searchBar, #"tableView": self.tableView, #"topLayoutGuide": self.topLayoutGuide};
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[searchBar]|" options:0 metrics:nil views:layoutViews]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[tableView]|" options:0 metrics:nil views:layoutViews]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[searchBar(44)][tableView]|" options:0 metrics:nil views:layoutViews]];
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSLog(#"Update should happen here");
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellID = #"CellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellID];
}
cell.textLabel.text = [NSString stringWithFormat:#"Cell number %ld", (long)indexPath.row];
return cell;
}
#end
It is embedded in a UINavigationController instance and initially runs as expect, like the following screenshots show:
Trouble arises when the searchBar gets activated. It seems to disappear from screen, but after carefully inspecting the view, we determine that it is actually onscreen, but with a width of zero. Here's a picture showing what is presented at this time:
I'm not that experienced with Auto Layout, so I'm left thinking there must be something wrong with my constraints, although I don't mess with them when activating the UISearchController.
Is there any way of making this work?
The UISearchController moves the search bar around when it's tapped, so it doesn't always play well with your constraints.
Instead of setting your constraints directly on the search bar, add an empty placeholder view that will hold your search bar and then place the search bar in it procedurally in viewDidLoad(). Set your constraints on this placeholder instead. Just match the search bar's frame to the placeholder's bounds and leave translatesAutoresizingMaskIntoConstraints set to true.
Sorry, I'm not sure how this placeholder view will handle the size change with the scope buttons. Hopefully you can figure out how to get that part working with auto layout after the change.
Related
UITableView is not visible on the UIViewController Class.
On Storyboard added a new UIViewController set to related SlideViewcontroller class to it, Add a new UITableView (tbl_Slide), set the datasource and delegate to UIViewController in storyboard for the added UITableView.
And also included the related datasource and delegate methods to the UIViewController class.
- (void)viewDidLoad {
[super viewDidLoad];
self.tbl_SlideMenu = [[UITableView alloc]
initWithFrame:CGRectMake(0, 80, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain];
self.tbl_SlideMenu.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
self.tbl_SlideMenu.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.tbl_SlideMenu.separatorColor = [UIColor lightGrayColor];
self.tbl_SlideMenu.dataSource=self;
self.tbl_SlideMenu.delegate=self;
[self.view addSubview:self.tbl_SlideMenu];
}
Since added the UITableView to the UIViewController for UIView, need not to induced above two lines of code
self.tbl_SlideMenu = [[UITableView alloc]
initWithFrame:CGRectMake(0, 80, self.view.frame.size.width,self.view.frame.size.height) style:UITableViewStylePlain];
[self.view addSubview:self.tbl_SlideMenu];
Once I included the allocation and added to subview its showing the data with tableview.
Once I removed allocation and frame added to subview is not visible.
So what is need of storyboard where I added UITableView to UIViewController for UIView (view default.) once Component added to storyboard and framed need not to allocate and frame in code.
Advance Thanks
Hope for best posible answers
If u added the tableview in storyboard there is no need to initialise the view components in the code in this case u don't need below lines as u mentioned
self.tbl_SlideMenu = [[UITableView alloc]
initWithFrame:CGRectMake(0, 80, self.view.frame.size.width,self.view.frame.size.height) style:UITableViewStylePlain];
however u need to create a outlet for your tableview to access the tableview in code that means as soon as view is loaded all your view components are initialised in your case tableview is initialised and u can ready to use it and also u don't need below lines of code if u set datasource and delegate in storyboard
self.tbl_SlideMenu.dataSource=self;
self.tbl_SlideMenu.delegate=self;
since u configured your tableview datasource and delegate and also added tableview to view controller's view there is no need of below line also
[self.view addSubview:self.tbl_SlideMenu];
and second way is as u mentioned creating the view in pure code, in this case u have to do all things by your self from initialising to adding the view component to controller's view as u mentioned like below
self.tbl_SlideMenu = [[UITableView alloc]
initWithFrame:CGRectMake(0, 80, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain]; //creating the tableview
self.tbl_SlideMenu.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
self.tbl_SlideMenu.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; //configuring the view
self.tbl_SlideMenu.separatorColor = [UIColor lightGrayColor];
self.tbl_SlideMenu.dataSource=self; //setting the datasource and delegate
self.tbl_SlideMenu.delegate=self;
[self.view addSubview:self.tbl_SlideMenu]; //adding it to tableview
hope u get this
Edit
it is working fine for me, i crossed checked it with some dummy values, for example as i mentioned , dragged and dropped a tableview, set its datasource and delegate to View Controller in storyboard and connected a outlet in ViewController.h file, like below,
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tbl_SlideMenu;
#end
and in ViewController.m file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.tbl_SlideMenu.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.tbl_SlideMenu.separatorColor = [UIColor lightGrayColor];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CELL"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CELL"];
}
cell.textLabel.text = #"Hello";
return cell;
}
#end
and i got output showing the tableview with 5 "Hello" on each row
I am new to iOS programming.
I have to implement a location search based on the third party map API, but I think I have messed up multiple view controllers.
Scenario:
I have a mapviewController for displaying the mapview. And I have a searchController for searchbar. There is a resultviewController property in searchController for display the search suggestions.
I have tried to add search VC as child VC to map VC, but once I click to the search bar it returns "Application tried to present modally an active controller".
So then I remove search VC from map VC & the search bar is not activated.
Therefore I want to ask how to handle these VCs, and avoid the case that map view covers the search bar and suggestion lists.
Thank you so much.
UPDATE:
I'm building a search bar in code. My aim is to build the following style in iOS.
like this http://i1.tietuku.com/cd4efa23d97af75ft.jpg
I pushed the map viewController to the navigation controller from menu.
[self.navigationController pushViewController:mapviewController animated:YES];
And trying to add a searchController to it.
- (void)viewDidLoad {
[super viewDidLoad];
_resultsTableController = [[UITableViewController alloc] init];
_searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsTableController];
_searchController.searchResultsUpdater = self;
[_searchController.searchBar sizeToFit];
_resultsTableController.tableView.tableHeaderView = _searchController.searchBar;
self.searchController.searchBar.delegate = self;
_resultsTableController.tableView.delegate = self;
_searchController.delegate = self;
_searchController.dimsBackgroundDuringPresentation = NO;
_searchController.searchBar.delegate = self;
mapView = [[BMKMapView alloc]initWithFrame:CGRectMake(0, kHeight(100), kScreen_Width , kScreen_Height-kHeight(100))];
[self addChildViewController:_searchController];
[self.view addSubview: _searchController.view];
[self.view addSubview:mapView];
}
for UISearchController you no need to add it as child view controller and and instant of using UITableViewController uses UITableView it make easy for you and
here below is code that is .m file
free to run that code and without uses storyboard.
#interface ViewController ()
{
UITableView *tableview;
UISearchController *searchcontroller;
NSMutableArray *array;}
#end
#implementation ViewController
(void)viewDidLoad
{
[super viewDidLoad];
array = [[NSMutableArray alloc]initWithObjects:#"one",#"two",#"three",#"four", nil];
tableview = [[UITableView alloc]initWithFrame:CGRectMake(0, 50, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)/2)];
[self.view addSubview:tableview];
tableview.dataSource = self;
tableview.delegate =self;
searchcontroller = [[UISearchController alloc]initWithSearchResultsController:nil]; // Create Reference of searchController
searchcontroller.searchResultsUpdater = self;
searchcontroller.searchBar.backgroundColor = [UIColor redColor];
searchcontroller.searchBar.barStyle = UIBarStyleBlack;
searchcontroller.searchBar.barTintColor = [UIColor whiteColor];
searchcontroller.dimsBackgroundDuringPresentation = false;
[searchcontroller.searchBar sizeToFit];
tableview.tableHeaderView = searchcontroller.searchBar;
MKMapView *mapview = [[MKMapView alloc]initWithFrame:CGRectMake(0, CGRectGetMaxY(tableview.frame), CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)/2)];
[self.view addSubview:mapview];
}
(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController;
{
NSLog(#"update ");
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
// Default is 1 if not implemented
{
return 1;
}
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return array.count;
}
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
}
cell.textLabel.text = array[indexPath.row];
return cell;
}
According to me you should use only one view controller which has a map on it. Over the map you can simply add custom search view and on typing/ taping search you can show search results using UITableview with some dropping animation keeping some max frame fixed, And finally on taping any result remove this UITableView and show location of map. If time permits I will create a sample for you, cant give assurance but will try. Mean while you can also go through Maps reference may be helpful
I am working on a iOS 8 app with Xcode.
I need to display a table with many columns and rows of data in one view.
Example:
Name Time In Time Out ETA
Johnnys Supplies 8:30AM 9:00AM 10:15AM
Franks Company 8:45AM 9:05AM 9:45AM
Another Inc. 10:12AM 11:00AM 12:04PM
All of the data would be read in with JSON/PHP.
I need it to work like a tableview where a user can scroll vertically, and select an index. Once that index is selected, the user can click a button to run additional queries based on the data in the selected cell (etc.).
What is the easiest way to implement this? There has to be a way xcode allows you to do this natively? Am I missing something?
All coding examples welcomed!
I have found two options but both require licensing fees:
http://www.ioscomponents.com/Home/IOSDataGrid <-- $400
http://www.binpress.com/app/ios-data-grid-table-view/586 <-- $130
Anyone familiar with these components?
What's the difference between two columns and two labels next to each other? A divider?
Is this a multi column table view?
Because it's a tableview with ordinary UITableViewCell that have 3 UILabels and 2 UIViews. The views pretend to be dividers by being 1 px wide.
Code should be self explanatory.
.h
#interface MultiColumnTableViewCell : UITableViewCell
#property (strong, nonatomic) UILabel *label1;
#property (strong, nonatomic) UILabel *label2;
#property (strong, nonatomic) UILabel *label3;
#end
.m
#interface MultiColumnTableViewCell ()
#property (strong, nonatomic) UIView *divider1;
#property (strong, nonatomic) UIView *divider2;
#end
#implementation MultiColumnTableViewCell
- (UILabel *)label {
UILabel *label = [[UILabel alloc] init];
label.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:label];
return label;
}
- (UIView *)divider {
UIView *view = [[UIView alloc] init];
view.translatesAutoresizingMaskIntoConstraints = NO;
[view addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:1.0/[[UIScreen mainScreen] scale]]];
view.backgroundColor = [UIColor lightGrayColor];
[self.contentView addSubview:view];
return view;
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
self.separatorInset = UIEdgeInsetsZero;
self.layoutMargins = UIEdgeInsetsZero;
self.preservesSuperviewLayoutMargins = NO;
self.divider1 = [self divider];
self.divider2 = [self divider];
self.label1 = [self label];
self.label2 = [self label];
self.label3 = [self label];
NSDictionary *views = NSDictionaryOfVariableBindings(_label1, _label2, _label3, _divider1, _divider2);
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-5-[_label1]-2-[_divider1]-2-[_label2(==_label1)]-2-[_divider2]-2-[_label3(==_label1)]-5-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:views];
[self.contentView addConstraints:constraints];
NSArray *horizontalConstraints1 = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_divider1]|" options:0 metrics:nil views:views];
[self.contentView addConstraints:horizontalConstraints1];
NSArray *horizontalConstraints2 = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_divider2]|" options:0 metrics:nil views:views];
[self.contentView addConstraints:horizontalConstraints2];
return self;
}
#end
TableViewController:
#implementation MasterViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[MultiColumnTableViewCell class] forCellReuseIdentifier:#"Cell"];
self.tableView.separatorColor = [UIColor lightGrayColor];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MultiColumnTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.label1.text = [NSString stringWithFormat:#"Name %ld", (long)indexPath.row];
cell.label2.text = [NSString stringWithFormat:#"Start %ld", (long)indexPath.row];
cell.label3.text = [NSString stringWithFormat:#"End %ld", (long)indexPath.row];
return cell;
}
#end
iOS table views are always a single column. On Mac OS you can create what you are after directly.
That said, you could create custom table view cells that display the content you want. In fact it would be quite easy. All you would do is to subclass UITableViewCell and define views (probably UILabels) for each of you columns, then wire them up as outlet properties in the cell. Then rig your table view to register that cell class for the cell identifier you use.
You then write your cellForRowAtIndexPath method to install your data into the different outlet properties.
You could also use a UICollectionView, but it looks to me like a table view with custom cells is a better fit for this application.
Use UICollectionView, check Apple WWDC 2012 sessions
205 Introducing Collection Views
219 Advanced Collection Views and Building Custom Layouts
from https://developer.apple.com/videos/wwdc/2012/
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];
}
The purpose is to implement a fixed search bar just like Contacts in iOS7.
I have a view controller called SearchViewController inherited from UIViewController.
And I add a searchBar and a tableView as its navigationController.view's subView.
But since searchBar and tableView are separated, when I start to search, no dim effect on tableView and result table view is shown in correctly.
I just want it behaves just like Contacts app.
Here is my code:
SearchViewController.h
#import <UIKit/UIKit.h>
#class UWTabBarController;
#class InfoSessionModel;
#interface SearchViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate>
SearchViewController.m
#import "SearchViewController.h"
#interface SearchViewController ()
#property (nonatomic, strong) UISearchBar *searchBar;
#property (nonatomic, strong) UISearchDisplayController *searchController;
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, strong) NSArray *data;
#end
#implementation SearchViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// initiate search bar
NSInteger statusBarHeight = 20;
NSInteger navigationBarHeight = self.navigationController.navigationBar.frame.size.height;
_searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, statusBarHeight + navigationBarHeight, 320, 44)];
// _searchBar.tintColor = [UIColor clearColor];
_searchBar.delegate = self;
_searchBar.barStyle = UIBarStyleDefault;
//NSMutableArray *scopeTitles = [[NSMutableArray alloc] initWithObjects:#"Employer", #"Program", #"Note", nil];
_searchBar.scopeButtonTitles = [[NSArray alloc] initWithObjects:#"Employer", #"Program", #"Note", nil];//[#"Employer|Program|Note" componentsSeparatedByString:#"|"];
// initiate search bar controller
_searchController = [[UISearchDisplayController alloc] initWithSearchBar:_searchBar contentsController:self];
_searchController.delegate = self;
_searchController.searchResultsDataSource = self;
_searchController.searchResultsDelegate = self;
// initiate table view
_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, statusBarHeight + navigationBarHeight, 320, [UIScreen mainScreen].bounds.size.height - statusBarHeight - navigationBarHeight)];
[_tableView setContentInset:UIEdgeInsetsMake(_searchBar.frame.size.height, 0, _tabBarController.tabBar.frame.size.height, 0)];
_tableView.delegate = self;
_tableView.dataSource = self;
[_tableView registerClass:[InfoSessionCell class] forCellReuseIdentifier:#"InfoSessionCell"];
[_tableView registerClass:[LoadingCell class] forCellReuseIdentifier:#"LoadingCell"];
[self.navigationController.view addSubview:_tableView];
[self.navigationController.view addSubview:_searchBar];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (_searchController.searchResultsTableView == tableView) {
return 1;
}
else {
return [data count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (_searchController.searchResultsTableView == tableView) {
static NSString *cellIdentifier = #"LoadingCell";
LoadingCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[LoadingCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.loadingLabel.text = #"Test cell for search result";
return cell;
}
else {
//... configure cell and return cell
return cell;
}
}
}
#pragma mark - UISearchDisplayController Delegate Methods
// hasn't been implemented
#pragma mark - UISearchBar Delegate Methods
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
//move the search bar up to the correct location
[UIView animateWithDuration:.3
animations:^{
searchBar.frame = CGRectMake(searchBar.frame.origin.x,
20,// status bar's height
searchBar.frame.size.width,
searchBar.frame.size.height);
}
completion:^(BOOL finished){
//whatever else you may need to do
}];
return YES;
}
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar {
//move the search bar down to the correct location
[UIView animateWithDuration:.25
animations:^{
NSInteger statusBarHeight = 20;
NSInteger navigationBarHeight = self.navigationController.navigationBar.frame.size.height;
searchBar.frame = CGRectMake(_searchBar.frame.origin.x,
statusBarHeight + navigationBarHeight,
_searchBar.frame.size.width,
_searchBar.frame.size.height);
}
completion:^(BOOL finished){
//whatever else you may need to do
}];
return YES;
}
This is the effects of my code:
All right, my problem is caused by my misunderstanding of views and navigationController's views.
In view did load method:
before is:
[self.navigationController.view addSubview:_tableView];
[self.navigationController.view addSubview:_searchBar];
but should be:
[self.view addSubview:_tableView];
[self.view addSubview:_searchBar];
In this way, the original table view and result table view will show correctly.
And other things are moving search bar up and down, these things should be done through UISearchBar delegate protocol methods and UISearchDisplayController delegate protocol methods.
This is a right way to implement a fixed searchBar and tableView bellow it.