Instead of using self.searchController.searchBar.removeFromSuperview() you should use:
navigationController?.dismissViewControllerAnimated(true, completion: nil)`
to dismiss the view. Also, you should give your segue an identifier and check for it in prepareForSegue. You implementation may look something like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ToDetail" {
let destination = segue.destinationViewController as! DetailViewController
navigationController?.dismissViewControllerAnimated(true, completion: nil)
//Pass Info to Detail View
}
}
and then in didSelectRowAtIndexPath just perform your segue with performSegueWithIdentifier.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("ToDetail", sender: self)
}
To allow the searchBar to reappear you can set up a boolean variable called searchBarShouldBeOpen on the main view controller. In your SearchAction function set this value to true, and then in viewWillAppear use an if statement with searchBarShouldBeOpen to decide whether to run SearchAction. Also, consider making SearchAction a regular function and moving everything but the last line shown in your example to viewDidLoad. Lastly, implement UISearchBarDelegate for your Main View Controller and override searchBarCancelButtonClicked and inside it set searchBarShouldBeOpen to false. Your Main View Controller would look something like this:
class ViewController: UIViewController {
//...Your Variables
var searchBarShouldBeOpen: Bool = false
let searchBarKey = "SearchBarText"
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
searchController.searchBar.delegate = self
searchController.hidesNavigationBarDuringPresentation = false
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Search", style: .Plain, target: self, action: #selector(ViewController.showSearchBar))
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if searchBarShouldBeOpen {
navigationController?.presentViewController(searchController, animated: false, completion: nil)
searchBarShouldBeOpen = true
if let previousText = NSUserDefaults.standardUserDefaults().stringForKey(searchBarKey) {
searchController.searchBar.text = previousText
}
}
}
func showSearchBar() {
navigationController?.presentViewController(searchController, animated: true, completion: nil)
searchBarShouldBeOpen = true
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ToDetail" {
let destination = segue.destinationViewController as! DetailViewController
if searchController.searchBar.text != "" {
NSUserDefaults.standardUserDefaults().setValue(searchController.searchBar.text, forKey: searchBarKey)
}
//Pass Info
}
}
//Your functions...
}
extension ViewController: UISearchBarDelegate {
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBarShouldBeOpen = false
}
}
In your Detail View Controller add this:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationController?.dismissViewControllerAnimated(true, completion: nil)
}
Edits:
Changed viewWillAppear to manually present the UISearchBar without animation rather than using showSearchBar so that it would not animate every time.
Added missing call to super.viewWillAppear(animated)
Moved the dismissal of the UISearchBar to the viewWillAppear of the detail view Controller so the search doesn't go away before the segue.
Persisted the UISearchBar's text using NSUserDefaults (in prepareForSegue) so that way it could be loaded in the viewWillAppear of the Main View Controller to set the search to what it previously was.
Added the searchBarKey constant to use as the key for the UISearchBar text persistence, so a "Magic String" would not be used to set and access the saved text.
Note: You should really consider using didSelectRowAtIndexPath to perform the segue.
Other Option: If you want the UISearchBar to animate out simultaneously with the transitioning of the Main View Controller to the Detail View Controller, you can use a custom segue (this will make the animation a bit smoother). I have made a custom segue example that creates this effect. Note that you will have to change the segue between the view controllers in Interface Builder to have kind "Custom" and be the following subclass of UIStoryboardSegue.
class CustomSegue: UIStoryboardSegue {
override func perform() {
let pushOperation = NSBlockOperation()
pushOperation.addExecutionBlock {
self.sourceViewController.navigationController?.pushViewController(self.destinationViewController, animated: true)
}
pushOperation.addExecutionBlock {
self.sourceViewController.navigationController?.dismissViewControllerAnimated(true, completion: nil)
}
pushOperation.queuePriority = .Normal
pushOperation.qualityOfService = .UserInitiated
let operationQueue = NSOperationQueue.mainQueue()
operationQueue.addOperation(pushOperation)
}
}
You can read more about the code in the custom segue here at the following links:
- Custom Segues: http://www.appcoda.com/custom-segue-animations/
- NSOperation: http://nshipster.com/nsoperation/
Hope this helps! If you need elaboration just ask! :)