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! :)