I have looked at other answers to this problem but they did not solve my problem.
This is my storyboard setup:
In my UITableViewController, if I set self.definesPresentationContext = true then the search bar will appear on every tab. If I don't, then the table will turn black after clicking search then switching to another tab and switching back.
Workaround 1: Dismiss searchController or set isActive to false in viewWillDisappear.
Problem: The search bar gets push down from the top every time I switch back and forth:
Workaround 2: Set searchController.searchBar.isHidden = true.
Problem: In my other tab which also uses UISearchController, it's not able to present the scope due to another search bar being already present (but hidden):
Attempt to present <UISearchController: 0x7ff81ac0aa30> on <xxx.ViewController: 0x7ff81ac0a6f0> which is already presenting (null)
I was having the same problem and was fixed, handling correctly the definesPresentationContext properly, so I just define this property to true in viewDidAppear and set it false in viewWillDisappear
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if(self.searchController == nil)
{
self.setupSearchBar()
}else{
self.definesPresentationContext = true
}
}
override func viewWillDisappear(_ animated: Bool) {
self.searchController!.isActive = false
self.searchController!.searchBar.removeFromSuperview()
self.definesPresentationContext = false
if(self.showingSearchBar)
{
self.rigthNavBarButtonAction()
}
super.viewWillDisappear(animated)
}
I hope this helps you
Using your Workaround 1, setting self.searchController!.isActive = true in viewDidAppear does the magic. You'd also need to restore the search bar text though.
Related
With the iOS 13 update, I've got an annoying bug that I still wasn't able to solve when I have the prefersLargeTitles = true on my UINavigationBar and I perform a push segue.
Plus, even if I'm not 100% sure if it's related to it, my view controller has a collection view embedded.
Anyway the bug/glitch I'm talking about is the following:
Basically the text doesn't animate as I would expect when I'm pushing, and it continues to stay there till the new screen is presented. Any tips? Thanks
I had the same issue. Try to set navigationItem.largeTitleDisplayMode to .always for your first VC and then .never for your second VC with prefersLargeTitles = true in both cases.
The reason is written from Apple Doc:
If the prefersLargeTitles property of the navigation bar is false, this property has no effect and the navigation item’s title is always displayed as a small title.
Which is causing the animation glitch, and it's not a iOS13 bug only, on iOS12/11 it's already the case it's just the other way around (the animation glitch is happening when dismissing from the secondVC back to the firstVC).
I wrote an article that explain a bit more about this:
https://www.morningswiftui.com/blog/fix-large-title-animation-on-ios13
Try to set largeTitleDisplayMode param inside viewWillAppear() method.
for the base VC set it to .always and in the destination VC set it to .never
BASE VC
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationItem.largeTitleDisplayMode = .always
}
DESTINATION VC
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationItem.largeTitleDisplayMode = .never
}
If I have a UITabBarController and do this inside one of its view controllers:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tabBarController?.tabBar.isUserInteractionEnabled = false
}
the first time it shows, I can still change tabs.
If I tap on another tab and tap back on the first tab, then the tabbar is really disabled, but not the first time.
Why? And how do I solve this?
EDIT:
There is one detail I noticed, the tabBarController?.tabBar.isUserInteractionEnabled = false has to be on the second view controller of a navigation controller. In other words:
Say I have that structure
UITabBarController
UINavigationController
UIViewController (1)
UIViewController (2)
UIViewController (3)
So if I add that viewDidAppear code on view controller (2), you can change the tab once, but not the second time (after you navigate to it, obviously).
And there is more, if I go back after navigating to view controller (2), the tab bar becomes "interactable" again, without my setting it to true.
Having a tab bar in view, but not being able to interact with it will probably be confusing and frustrating for the user. And while I don't have the reason or solution for the original question, I have an alternative suggestion:
Hide the tab bar in UIViewController (2):
override func viewDidLoad() {
super.viewDidLoad()
tabBarController?.tabBar.isHidden = true
}
We're putting this in viewDidLoad so it's hidden as soon as the view
appears.
This also requires that you explicitly unhide it in UIViewController (1) for when the user hits the back button. Do it in viewWillAppear since the view was loaded already and we're going back to it.
override func viewWillAppear(_ animated: Bool) {
tabBarController?.tabBar.isHidden = false
}
While I have experienced the same behavior with:
tabBarController?.tabBar.isUserInteractionEnabled = false
..what you CAN do is disable each of the items in the tabBar.items collection, and then re-enable them in the viewWillAppear method of another controller. For example, if you didn't want your users tabbing out of menu #1 once they are inside it, you could do something like this in the subsequent controller(s):
override func viewWillAppear(_ animated: Bool) {
//0th tab items remains enabled as "only choice" for user
self.tabBarController!.tabBar.items![1].isEnabled = false
self.tabBarController!.tabBar.items![2].isEnabled = false
self.tabBarController!.tabBar.items![3].isEnabled = false
self.tabBarController!.tabBar.items![4].isEnabled = false
}
when the user tabs back to first tab (0) (or hits the back button), in that viewController's viewWillAppear method, re-enable the items:
override func viewWillAppear(_ animated: Bool) {
//re-enable tab items
self.tabBarController!.tabBar.items![1].isEnabled = true
self.tabBarController!.tabBar.items![2].isEnabled = true
self.tabBarController!.tabBar.items![3].isEnabled = true
self.tabBarController!.tabBar.items![4].isEnabled = true
}
Now I have a viewController(A) which is root view controller for Navagation Controller followed by Tab Bar Controller, I want to perform segue from it to another viewController(B), totally replace the A.
Therefore I applied show detail(replace), it worked well as what I think in other cases. However in this case, when A segued to B, the navigation bar and Tab bar still existed. Why this happened and how to solve it?
In viewController(A) you have to write
override func viewWillAppear(_ animated: Bool) {
self.tabBarController?.tabBar.isHidden = false
self.navigationController?.navigationBar.isHidden = false
}
and in viewController(B) you have to write
override func viewWillAppear(_ animated: Bool) {
self.tabBarController?.tabBar.isHidden = true
self.navigationController?.navigationBar.isHidden = true
}
I'm working with two table view controllers. When a button is pressed on a cell from table view a, table view b comes up on top of a.
In the code for tableview a I wrote that when the button that takes you to table b is pressed self.tabbarcontroller?.tabbar.hidden = true.
That worked for hiding the tabbar but when i put the code in the second table view self.tabbarcontroller?.tabbar.hidden = false the tabbar doesnt come back.
// present view controller
let vieww = self.storyboard?.instantiateViewControllerWithIdentifier("viewTable") as! viewsVC
vieww.view.backgroundColor = .lightGrayColor()
vieww.view.alpha = 0.9
vieww.modalPresentationStyle = .OverCurrentContext
vieww.hidesBottomBarWhenPushed = true
self.presentViewController(vieww, animated: true, completion: nil)
// hide tabbar
self.tabBarController?.tabBar.hidden = true
Add the code
self.tabBarController?.tabBar.hidden = false
to the ViewDidAppear method, rather than the viewDidLoad method in the original tableViewController.
The issue you are encountering is that the view is not loaded after you go back, but rather appears right away since it has already been loaded beforehand.
It should look like this:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.tabBarController?.tabBar.hidden = false
}
This should fix the problem.
Good luck with your project!
I'm addapting this code in my project https://github.com/stuartbreckenridge/UISearchControllerWithSwift
After Navigation Controller and before Countries Scene (ViewController) I have put one more View Controller, so now in Countries View controller I have back button. After inputing something in search bar when I press Back, search bar still is visible.
I've tried hide it doing this (countrySearchController is UISearchController):
override func viewWillDisappear(animated: Bool) {
self.countrySearchController.active = false
}
But it hides UISearchController with delay, so it's stil visible for half a second.
Input something:
And then press back:
Correct way probably is to set self.definesPresentationContext in viewDidLoad
self.definesPresentationContext = true
That caused some glitches when UISearchController became active, so I just removed the searchBar from Superview.
override func viewWillDisappear(animated: Bool) {
searchController.searchBar.removeFromSuperview()
searchController.active = false;
super.viewWillDisappear(true)
}