I have a problem with a UISearchBar. When ill search some Text in combination with an UITableView, and ill click on one result Cell, the UISearchBar is still visible in the next View Controller. If ill go back (with Segues) - the UISearchbar is still there (with the Keyword)
So after ill click on one result, ill get (in the next View Controller):
Ill use it this way:
class ...: UITableViewController, UISearchResultsUpdating {
var filterSearchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
filterSearchController.searchResultsUpdater = self
filterSearchController.hidesNavigationBarDuringPresentation = false
filterSearchController.dimsBackgroundDuringPresentation = false
filterSearchController.searchBar.searchBarStyle = .Minimal
filterSearchController.searchBar.sizeToFit()
self.tableView.tableHeaderView = filterSearchController.searchBar
Any ideas what could be a problem?
You need to dismiss the UISearchController yourself before transitioning to the next view controller with:
filterSearchController.active = false
Related
I have an UITableView which works perfectly fine. It is nested in a UITabbarController.
I also integrated an UISearchController with a UISearchBar, which lets the user search the content of the UITableView. This also works fine.
When you select one of the TableViewCells, you get to a DetailView.
When you do this without active search, everything works fine, but when you enter a searchterm and you choose a cell from the results, there is no way to get back to the TableView as there is no back button in the top left corner, neither can you use the swipe back gesture.
I may have to add, that I do not specify a separate UITableView for the searchresults:
self.searchController.searchBar.delegate = self
self.searchController.searchResultsUpdater = self
self.tableView.tableHeaderView = self.searchController.searchBar
self.definesPresentationContext = true
I define the SearchController like this:
var searchController: UISearchController = {
let controller = UISearchController(searchResultsController: nil)
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
return controller
}()
I thought, that maybe I have to put a UINavigationController into the UITabbarController and set my TableView as its RootViewController, but then I had the problem, that the SearchBar was hidden behind the NavigationBar...
EDIT (#ryantxr):
my didSelectRowAtIndexPath:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
in cellForRowAtIndexPath there is no difference between search and no search as the cells look the same. This is also the reason, why I don't use two different segue yet.
But you are right, I don't use different segue when using search and no search. The only segue used when a cell is clicked is setup in the storyboard and in prepareForSegue I set the attributes of the target UIViewController, which also works fine.
Turns out that the problem was this little piece of code in the UITableViewController which contains the UISearchController was responsible for this:
self.definesPresentationContext = true
by deleting this, the result view controller was shown correctly and the navigationbar did not disappear so it was possible to go back to the searchresults ect...
Problem:
I have a table view that the user can either scroll through to find something or use a search bar. The search bar was not created using the StoryBoard. My view has a UISearchController that handles the search bar and search result updating. The issue that I'm running into is that since my SearchResultsController is instantiated by another controller I cannot perform a segue to another view, or at least I can't find the solution. Everything works except for the segue between my Search Results Controller and the view it's destined for.
What I would like to do
Have my MyNavTableViewController delegate for MySearchResultsController. In the search results controller it will segue to another view when the user taps on a TableViewCell. I'm not using the StoryBoard to accomplish this I'm having difficulty using segues to transition to another view.
If I can't get this to work what I will probably do:
It's essential that I pass information between views, and for me I've always done it using segues. However if this doesn't work I will probably try presenting a view modally by pushing it unto the navigation controller stack and write the data to a shared database or something. I would prefer to use a segue though.
Research:
There is definitely more than this, but I'm not going to take too much space on urls.
Creating a segue programmatically
https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html
My Setup
I'm going to try and keep this as concise as possible. There is more code than what I'm displaying. I'm just going to try and clean it up so that I'm only presenting the important stuff. I'm also changing a few names around because there may be sensitive information. It's probably not a big deal, but I'd rather be safe.
class MyNavTableViewController: UIViewController, UITableViewDataSource{
//this is
#IBOutlet weak var tableView: UITableView!
var searchController: UISearchController!
override func viewDidLoad(){
...code
tableView.registerClass(UITableViewCell.self,forCellReuseIdentifier: tblId)
let resultsController = MySearchResultsController()
resultsController.databaseFilePath = databaseFilePath()
//this is essential that I use a segue because between my views I'm passing information between them.
resultsController.photo = photo!
searchController = UISearchController(searchResultsController: resultsController)
let searchBar = searchController.searchBar
searchBar.placeholder = searchBarPlaceHolderText
searchBar.sizeToFit()
tableView.tableHeaderView = searchBar
searchController.searchResultsUpdater = resultsController
}
}
MySearchResultsController: UITableViewController, UISearchResultsUpdating {
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
//self.performSegueWithIdentifier(imagePrepareStoryBoardId, sender: tableView.cellForRowAtIndexPath(indexPath))
/*let imagePrepare = ImagePrepareController()
customSegue = SearchResultSegue(identifier: imagePrepareId, source: self, destination: imagePrepare)*/
//neither storyboard nor navigationController can be nil.
let destVC = self.storyboard!.instantiateViewControllerWithIdentifier(imagePrepareStoryBoardId)
//destVC.photo = photo!
//self.presentViewController(destVC, animated: false, completion: nil)
self.navigationController!.pushViewController(destVC, animated: false)
}
}
My Failed Attempts
1) Straight up segue - Doesn't work since the MySearchResultsController is not a view in the storyboard. Everything from what I've read is that segues can only be created in the SB.
2) Push view onto the navigation stack. The only problem with this is that I can't send data between views (or at least from what I've read). I'm also getting this error right at this break point:
let destVC = self.storyboard!.instantiateViewControllerWithIdentifier(imagePrepareStoryBoardId)
fatal error: unexpectedly found nil while unwrapping an Optional value
I double checked the imagePrepareStoryBoardId. It's correct.
3) Use custom segue - As you can see from the commented out lines that this isn't working either. I've always used segues with the SB so this method is a little new to me. I might be messing it up somewhere.
First create a protocol
protocol SelectedCellProtocol {
func didSelectedCell(text: String)
}
on your UITableViewClass declare it
class MySearchResultsController: UITableViewController, UISearchResultsUpdating {
var delegate:SelectedCellProtocol?
}
and on the selected cell method call it like :
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
self.delegate?.didSelectedCell(cell.textLabel?.text)
}
when you declare your results controller, set the delegate
let resultsController = MySearchResultsController()
resultsController.databaseFilePath = databaseFilePath()
//this is essential that I use a segue because between my views I'm passing information between them.
resultsController.photo = photo!
resultsController.delegate = self
searchController = UISearchController(searchResultsController: resultsController)
let searchBar = searchController.searchBar
searchBar.placeholder = searchBarPlaceHolderText
searchBar.sizeToFit()
tableView.tableHeaderView = searchBar
searchController.searchResultsUpdater = resultsController
and then implement the protocol
class MyNavTableViewController: UIViewController, UITableViewDataSource, SelectedCellProtocol{
func didSelectedCell(text: String) {
print(text)
//make your custom segue
}
}
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
I have made a UITableView Controller with a UISearchBar as the Table's header.
I have then embedded this View Controller into a UINavigationController, as the root view controller.
Now, when I tap on the Search Bar, the SearchBar seems to disappears and displays a white screen. The keyboard appears, but there is no Search Bar.
The Table View can scroll, but the search bar has simply vanished.
When I implement this UITableViewController without the Navigation Controller, it works perfectly. But something about the Navigation Controller is borking everything up.
I've had the same issue that was sometimes happening, especially with table view of small number of rows (less than 50).
It appears the searchBar is removed from the view hierarchy, precisely from the container view that is a child of the UISearchControllerView.
I've found a workaround to manually add back the searchbar as a subview of the UISearchControllerView container child. This is implemented in the delegate function (from UISearchControllerDelegate) didPresentSearchController:
func didPresentSearchController(searchController: UISearchController) {
if searchController.searchBar.superview == nil {
for searchCtrlChildView in searchController.view.subviews {
if searchCtrlChildView.frame.origin == CGPoint(x: 0, y: 0) { //Discriminate if by chance there was more than one subview
searchCtrlChildView.addSubview(searchController.searchBar)
break
}
}
}
}
I've also filed a radar to Apple on this as it is not fixed in iOS 8.4
Check the way I had my searchBar it in viewDidLoad
I have my viewController embedded in NavigationController too
My code (hope it helps) :
class myTableViewController: UITableViewController,UISearchResultsUpdating,UISearchControllerDelegate,UISearchBarDelegate
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
self.tableView.tableHeaderView = controller.searchBar
return controller
})()
So, I am currently trying to replace the depricated searchDisplayController in one of my projects with UISearchController and I am running into this problem.
If there are no results in the search (the UITableView is empty) the whole ViewController is dismissed. This does not happen when the search results are not empty. I wan't to make it clear I am not using a UITableViewController. Instead I have a regular VC with a UITableView in it.
Here is some of my code:
var resultSearchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.delegate = self
controller.searchBar.delegate = self
self.studentTable.tableHeaderView = controller.searchBar
return controller
})()
....
}
Now, if I add this function to the equation the cancel button always dismisses the VC.
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
resultSearchController.active = false
}
So why exactly does setting the searchController.active = false dismiss the VC? Is it because it is using the same UITableView as the VC? I believe that the old searchDisplayController would just display a UITableView over the one being used. If this is the case is there a way to override the dismissVC?
this is also Happening to me. The Way I Solve it is by Replacing:
resultSearchController.active = false
with
resultSearchController.searchBar.text = ""
resultSearchController.searchBar.resignFirstResponder()
I Hope this helps you :-)
2018 Just wanna share the fruits of my 1-2 hours debugging.
I had multiple issues with using UISearchController with UITabBarController, namely:
This one, this very question of the OP. Hitting cancel button dismisses the screen that is presenting the searchController.
The tab (or the screen) becomes black, Tab Bar and UISearchController giving black screen
Using UISearchController inside the title view of the navigation bar of UINavigationController in both iOS 10, 11, and 12, like this questions. UISearchBar increases navigation bar height in iOS 11
And for the solution for #3, since we're already here: https://stackoverflow.com/a/53264329/3231194
Finally, the ONLY solution that I have been seeing all this time is adding this code:
self.definesPresentationContext = true
The issue is that I was putting this in a wrong function.
Remember, that solution solved the #1, and #2 problem that I had. Nothing more, nothing less.
Where to add that? Inside the viewDidAppear. That's it!