I'm creating an iOS 9.3 app using Swift and Xcode 7.3.
It displays a list of food categories (table view). Each category contains food items (collection view). Each item has a simple detail page. This view hierarchy is managed by one navigation controller.
I implemented a global (category-agnostic) food item search bar using UISearchController. The search bar is visible in the category view which, however, uses my food item view to display the results. (The results are items, not categories).
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let ficId = "FoodItemsCollectionControllerId"
let fic = storyboard.instantiateViewControllerWithIdentifier(ficId)
as! FoodItemsCollectionController
searchController = UISearchController(searchResultsController: dic)
fic.searchController = searchController
searchController.searchResultsUpdater = fic
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
searchController.searchBar.sizeToFit()
navigationItem.titleView = searchController.searchBar
searchController.hidesNavigationBarDuringPresentation = false
Problem: Whenever I search for an item and click on it, the food item detail view segue cannot be pushed as the item view is not embedded into my navigation controller. I can present the view modally, with no navigation bar (and no way to go back). I could implement a back button by hand, but I'd like an elegant navigation controller solution.
Tried: Pushing, adding and setting the item view controller(s) manually onto the navigation controller. However, it seems to get ignored whenever I set searchResultsController to it when constructing a UISearchController.
navigationController?.addChildViewController(fic)
navigationController?.pushViewController(fic, animated: true)
navigationController?.viewControllers = [fic, self]
Idea: Use
searchController.presentationControllerForPresentedViewController(*, presentingViewController: *, sourceViewController: *)
I didn't find good documentation and didn't manage to avoid instance-selector errors at runtime though.
Related
Hello I have a searchController which disappears on click on one of the search items that appeared before the new view displays. What I would like is for the search controller to stay active so when the user goes back to the view they still see the list of results. currently I display the search controller with a present function. Any ideas how to stop this from leaving the screen? Thank you in advance!!
MainViewController:
func searchButtonClicked(){
self.searchController?.isActive = true
self.searchController?.searchBar.becomeFirstResponder()
if let controller = self.searchController {
present(controller, animated: true, completion: nil)
}
}
func searchItemClicked(){
self.searchController?.isActive = false
//set up detail controller and push
let vc : detailViewController =self.storyboard?.instantiateViewController(withIdentifier:"DetailViewController")
self.navigationController?.pushViewController(vc, animated: true)
}
func setupSearch(){
self.searchController = UISearchController.init(searchResultsController: searchResultsCustomController)
self.searchController?.obscuresBackgroundDuringPresentation = true
self.searchController?.searchBar.delegate = self
self.searchController?.searchBar.showsCancelButton = true
self.searchController?.searchBar.placeholder = "Search for people or places"
}
EDIT:
To add more information regarding this error. The navigation bar has a search button which the user clicks to do a search. From here the searchController is started and a search bar appears. Upon entering credentials for the search the table view appears with results. If the user clicks on one of this results, the table view and the search bar disappear by going up as if I pressed the cancel button, and then the screen is pushed to the detail view controller.
For anyone running into this issue all you have to do is add the following line of code on your viewdidload function:
self.definesPresentationContext = true
I am trying to display a fix navigation bar for my UiTableViewController, I have a first ViewController and when I click on it, this will open my UITableViewController Here is the code of the click :
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("MyTableViewController") as! MyTableViewController
vc.myObject = object // I pass some data
presentViewController(vc, animated: true, completion: nil)
the UItableView is correctly display but not navigation bar appear, if I add one, the navigation bar scroll with the table view and I don't want this behavior.
I tried this without success :
Go to the Editor menu, and click on the Embed In submenu, and choose
Navigation Controller
And tried to change some settings here :
Actually, in your case you want to show navigation and for navigation you have to push your view controller to a UINavigationController thats why the solution is :
let vc = storyboard.instantiateViewControllerWithIdentifier("MyTableViewController") as! MyTableViewController
vc.myObject = object // I pass some data
self.navigationController?.pushViewController(vc, animated: true)
presentViewController offers a mechanism to display a modal view controller; i.e., a view controller that will take full control of your UI by being superimposed on top of a parent controller & establish a parent child relation b/w presenting & presented view controllers.
where as
pushViewController offers a much more flexible navigation process where you can push & pop a new controller to UINavigationController, so to go back to the previous one, in a ordered way. Imagine that controllers in a navigation controller will just build a sequence from left to right like building a stack of view controllers stacking upon each other.
Do it this way:
let vc = storyboard.instantiateViewControllerWithIdentifier("MyTableViewController") as! MyTableViewController
vc.myObject = object // I pass some data
self.navigationController?.pushViewController(vc, animated: true)
I currently have my UISearchController set up so it is presented over the nav bar once the search icon is clicked.
var searchController: UISearchController!
#IBAction func searchMe(sender: UIBarButtonItem) {
// Create the search results view controller and use it for the `UISearchController`.
let searchResultsController = storyboard!.instantiateViewControllerWithIdentifier(SearchResultsViewController.StoryboardConstants.identifier) as! SearchResultsViewController
// Create the search controller and make it perform the results updating.
searchController = UISearchController(searchResultsController: searchResultsController)
searchController.searchResultsUpdater = searchResultsController
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.tintColor = Colors.blue
searchController.searchBar.barTintColor = UIColor.whiteColor()
// Present the view controller.
presentViewController(searchController, animated: true, completion: nil)
}
I am using a different searchResultsController than the current table view to display results. The problem is that when a cell is selected in the searchResultsController a segue is performed to a new view controller (the users profile) and there is no navigation bar.
I need a back button to appear to take the user back to the searchResultsController. I have tried a bunch of different segues, setting the nav bars on the storyboard but nothing seems to work. My initial thought was to make this line of code:
searchController = UISearchController(searchResultsController: searchResultsController)
point to a nav controller with searchResultsController as its root view controller but I had no luck. Any help is great! Thank you!
In my code this is how I setup UISearchController:
searchResultController = storyboard!.instantiateViewControllerWithIdentifier(DBSearchResultControllerIdentifier) as! DBSearchResultController
searchController = UISearchController(searchResultsController: searchResultController)
searchController.searchResultsUpdater = self
searchController.delegate = self
searchResultController.tableView.tableHeaderView = searchController.searchBar
on some action all I do is:
#IBAction func cityButtonTapped(sender: UIButton) {
searchController.active = true
}
But then I have an error:
Application tried to present modal view controller on itself. Presenting controller is UISearchController: 0x7f9a0c04a6a0
The apple documentation for UISearchController clearly says the following things:
Setting active property to YES performs a default presentation of
the search controller.
Set the searchResultsController parameter to nil to display the
search results in the same view that you are searching.
So it looks like you are using your current view controller itself as your searchResultsController and hence when you try to set active to YES, it tries to modally present the your current view on itself and hence the error.
I AM NOT USING STORYBOARD SEGUES.
When I use UISearchController to have a search bar at the top of my table view, I get extremely strange behavior. Is there documentation on how I'm supposed to handle the search bar when a view dismisses? When I switch to a new view controller via an animation or push one on a nav stack, the bar is stuck in its spot until I hit the "Cancel" button.
See a video of what's happening in this short clip:
https://www.youtube.com/watch?v=6G7xFMENm_o&feature=youtu.be
This is the code, in the view controller, that sets up search bar:
var s: UISearchController!
private func configureSearching() {
s = UISearchController(searchResultsController: nil)
s.searchResultsUpdater = self
s.dimsBackgroundDuringPresentation = false
s.searchBar.searchBarStyle = .Minimal
s.hidesNavigationBarDuringPresentation = false
tableView.tableHeaderView = s.searchBar
s.searchBar.sizeToFit()
}
you should add the following line in viewDidLoad
self.definesPresentationContext = true