How to show/hide a search bar inside a navigation bar (iOS 8) as in Apple's Calendar app? - uibarbuttonitem

How to implement: I have UIBarButtonItem with a search icon, after I click on it, I want to show the search bar in navigation bar and on click cancel button in search bar, I want to show navigation bar without search and with buttons and title like in IOS 7 calendar app.

Setup an action for your search button to present a UISearchController. See the Search > Present Over Navigation Bar demo in Apple's UICatalog sample code:
- (IBAction)searchButtonClicked:(UIBarButtonItem *)sender {
// Create the search results view controller and use it for the UISearchController.
AAPLSearchResultsViewController *searchResultsController = [self.storyboard instantiateViewControllerWithIdentifier:AAPLSearchResultsViewControllerStoryboardIdentifier];
// Create the search controller and make it perform the results updating.
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
self.searchController.searchResultsUpdater = searchResultsController;
self.searchController.hidesNavigationBarDuringPresentation = NO;
// Present the view controller.
[self presentViewController:self.searchController animated:YES completion:nil];
}

Related

How to restrict UISearchController from hiding view Navigation Bar in IOS8

I have a UIViewController embedded in a popover. This controller has two subviews, a UINavigationBar and a MapView. I try to implement the new search Controller i.e. UISearchController as UISearchDisplayController is deprecated in iOS8.
When I click in the search bar (displaying two scopes), everything is all right, and the navigation bar is still visible. But when I start typing in the search bar, the navigation bar and the keyboard disappear, replaced by a dim map view. I tried to add self.searchController.hidesNavigationBarDuringPresentation = NO; in the updateSearchResultsForSearchController: method as well as searchBarShoulBeginEditing: method, but got no result. (note that the controller viewDidLoad defines self.definesPresentationContext = YES;)
Any idea to force navigation being displayed anytime?
First set this property self.definesPresentationContext = YES; in ViewDidLoad. Then implement searchBarTextShouldBeginEditing and searchBarTextDidBeginEditing methods as such:
-(void)searchBarTextShouldBeginEditing:(UISearchBar *)searchBar {
[searchControllerMain setActive:YES];
[searchControllerMain.searchBar becomeFirstResponder];}
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchControllerMain setActive:YES];
[searchControllerMain.searchBar becomeFirstResponder];
searchControllerMain.hidesNavigationBarDuringPresentation = NO;
}
It will work!!

Changing properties of container view

I have a tabView with let's say 3 tabs, each of the tabViewItems contains a webView. I want to set the title of each tab as the document.title of the HTML page each webView is rendering.
So basically, each NSTabViewItem has a Webview, via [tabViewItem setView:webView];.
Now, on the didFinishLoadForFrame delegate of the webviews, I can retrieve the title of the HTML page by doing a NSString *title = [sender stringByEvaluatingJavaScriptFromString:#"document.title"]. I only have access to the sender object, so my question is how can I get the NSTabViewItem containing my sender. In other words, what should I put inside the < >s
[<getNSTabViewItemFromSender:sender> setLabel:title]
You can get the parent of any NSView by sending it -superview.
Since your web view object is setup as the view for the tab, you can find the tab item that is using your specific web view.
You can implement this as a category on NSTabView (something like this)...
- (NSTabViewItem*)tabViewItemWithView:(NSView*)view {
for (NSTabViewItem *item in [self tabViewItems]) {
if (item.view == view) {
return item;
}
}
return nil;
}
Then, you can set the label for the tab item that contains your web view.
[[tabView tabViewItemWithView:webView] setLabel:label];

How To Correctly Segue To An Embedded Tab Bar and Navigation Controller Using Storyboards?

I've got an app where the user selects their country from a picker wheel. An alert comes up and asks them to confirm the change. If they confirm, it takes them to a different view where they can then select from a list of categories to display information...
The list of categories is embedded in a Navigation Controller to facilitate moving from the detailed view "Back" to the category select view.
The entire app is embedded in a Tab Bar Controller.
It works fine (after selecting their country they are taken to the Select Category screen) except that now the Select Categories has lost its connection to the Tab Bar Controller and there is no way to get back to other parts of the app.
Here's my alertView code:
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSLog(#"ok");
//I tried the following but it doesn't do anything
//SelectCategory *switchtocategory = [[SelectCategory alloc] init];
//[self.navigationController pushViewController:switchtocategory animated:YES];
//the following works but loses the tab/navigation bars
[self performSegueWithIdentifier: #"GoToCategory" sender: self];
} else {
NSLog(#"cancel");
}
}
Finding the answer was really about understanding the role of the Tab Bar Controller, how it defaults as the root view controller and then how to work with it to access the various view controllers, instead of trying to segue. Reading the Apple documentation helped with this but the code turned out to be very easy:
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
NSLog(#"ok");
//the following transitions to tab #3 when the alertView is touched/clicked/dismissed
[self.tabBarController setSelectedIndex:2];
} else {
NSLog(#"cancel");
}
}

How to add the Navigation Bar's view to a PopOver's PassThroughViews?

I have a PopoverController view that allows a user to download a file. On button press, the popOver view will expand in size, display download status, and the main view controller will be obscured by an unhidden "cover" view that has been added to the PopoverController's "passThroughViews" property so that the user can not accidentally dismiss the pop over while the file is downloading.
My problem is that, in storyboards, my main viewController is embedded in a Navigation Controller. I can't seem to cover the navigation controller's bar with a view in the storyboard, and if the user presses anywhere on the navigation bar then the popover will disappear and the user will lose the download's progress bar.
How do I either cover up the navigation bar with my "cover" view, or how do I add the navigation bar's view to my popOverController's passThroughViews?
Opening the Popover from the main viewController:
- (IBAction)openDataOptionsPopOver:(id)sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
PopOverViewController *optionsWindow = [storyboard instantiateViewControllerWithIdentifier:#"dataOptions"];
self.popUp = [[UIPopoverController alloc] initWithContentViewController:optionsWindow];
[self.popUp setDelegate:self];
[nextNavButton setEnabled:NO]; //Disabling barButtonItem on the navigationController
optionsWindow.containerPopOver = self.popUp; //Pointer to the popover, to resize it later.
optionsWindow.coverView = self.coverView; //Pointer to the coverView, to (un)hide later
[popUp presentPopoverFromRect:[sender frame] inView:[sender superview] permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
Setting the passThroughViews property inside of the PopoverViewController:
//Expands the popOver on press of "refreshFileButton" to display progressView
-(void) explodeWindow
{
//setting self.navigationController.view and ...visibleViewController.view here didn't seem to work ...
[containerPopOver setPassthroughViews:[NSArray arrayWithObjects:coverView, nil]];
[containerPopOver setPopoverContentSize:CGSizeMake(600, 400) animated:YES];
[titleBarItem setTitle:#"Downloading File. Please Wait ..."];
[refreshFileButton setHidden:YES];
[progressView setHidden:NO];
[downloadLabel setHidden:NO];
[coverView setHidden:NO];
[progressView setProgress:0.0 animated:NO];
}
I've tried adding self.navigationController.view to passThroughViews with no success--it actually turns out to be a null pointer. And I can't seem to place a UIView at any level in storyboards that will cover all my controls without obscuring the popOver. What am I missing here? And thanks for reading.
Edit:
As Aglaia points out below out, implementing the following, and avoiding passThroughViews, is probably the best way to do this.
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
//Don't dismiss our popover when the view covering our controls is present
if([coverView isHidden]){
return YES;
}else{
return NO;
}
}
Maybe there is something I am missing, but why don′t you just implement a new view controller with its navigation bar set to none and present it modally on button press? Then when the download is finished you just dismiss the view controller.
If you want the user to see the underlying view you can use a UIAlertView instead.
Alternatively set you view controller as the delegate of the popover controller and forbid the user to dismiss your popover on touch outside through
- (BOOL) popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
return NO;
}
Then when you want to dismiss it call dismissPopoverAnimated:
to cover the whole screen including navigation bar:
[myView setFrame:[[UIScreen mainScreen] bounds];
[self.navigationController.view addSubview:myView];

UINavigationBar title

I need a custom leftBarButtonItem on my navigation bar because I need to perform a function in the view controller when the view is popped. I would like to have the back button have the correct title (of the view controller below). So two questions:
1) Can I get the title of the standard backBarButton item somehow, so that I can manually set my custom button's title?
or
2) Is there another hook/event that I can use that is only called when the user pops the view?
Re 2: I found one solution using:
NSArray *viewControllerArray = [self.navigationController viewControllers];
int parentViewControllerIndex = [viewControllerArray count] - 2;
But this array is (null) for me.
PS I'm using Three20.
There's a UIViewController function which gets triggered when the view controller disappears from the screen:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
.....
}

Resources