How to hide the transition searchBar next screen - ios

Added The Search bar TableView, but when one of the items that were looking for and the transition to his page SearchBar and module typing is not removed and remains on the screen. How can we make the transition to searchbar module typing cleaned?

If Have you have used UISearchController,put viewWillDisappear: in viewController.
//this is my searchController, created programatically
var searchController : UISearchController?;
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated);
if let sc = self.searchController where sc.active {
self.searchController?.dismissViewControllerAnimated(false, completion: nil);
}
}
Reason :
UISearchController is subclass of UIViewController.
If your search bar is active, that means it over your current viewController. so before going out from your viewController you need to check if it is active or not, by using its property .active.

Related

UISearchController / UINavigationBar shows broken animation when used within UINavigationController

I have this NavigationController hat has Large Titles enabled for its NavigationBar. The root ViewController has a SearchController, and hidesSearchBarWhenScrolling is set to True in the ViewController's NavigationItem as I don't want the SearchBar to be always visible. The ViewController has a TableView and when you tap on one of its items a new instance of the same ViewController will be pushed onto the Navigation stack using a storyboard segue. However, when looking at the transition between the current and the new ViewController one can observe that the animation doesn't look right: As soon as the new ViewController is moved in the SearchBar becomes empty, just showing its background. When the new ViewController is finally fully visible, the SearchBar will go away without any animation.
This is how I add the SearchController (nothing fancy here):
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let searchController = UISearchController(searchResultsController: nil)
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = true
}
}
And so it looks like when navigating from "One" to "Two":
UISearchController / UINavigationBar shows broken animation when used within UINavigationController
Is there a way to make this look nicer? Of course, in the new ViewController the SearchBar should not be initially visible, so it has to go away somehow. But I would think that the SearchBar on the old ViewController perhaps should be faded out somehow instead of staying there and then suddenly hiding when the transition to the new ViewController is finished. Hopefully I'm just doing something wrong here...
Thanks and Merry Xmas to all of you,
Peter
Try setting the search controller to nil in the viewWillDissappear method.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationItem.searchController = nil
}
Well, I finally found something very useful that I just couldn't find before asking my question:
Broken UISearchBar animation embedded in NavigationItem
Too bad this is known since iOS 11 and still not fixed.

Accessibility set focus to navigation bar title item

Overview:
I would like to set the accessibility focus to the navigation bar's title item.
By default the focus is set from top left, meaning the back button would be on focus.
I would like the title item to be in focus.
Attempts made so far:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
navigationController?.navigationBar.items?.last)
Problem:
The above code makes no difference, the back button is still in focus.
Possible Cause:
Not able to get the item corresponding to the title to be able to set the focus.
Solution 1
I don't like it, but it was the minimum amount of hacking that does not rely on digging through hidden subviews (internal implementation of UINavigationBar view hierarchy).
First in viewWillAppear, I store a backup reference of the back button item,
and then remove the back button item (leftBarButtonItem):
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
backButtonBackup = self.navigationItem.leftBarButtonItem
self.navigationItem.leftBarButtonItem = nil
}
Then I restore the back item, but only after I dispatch the screen changed event in viewDidAppear() :
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
self?.navigationItem.leftBarButtonItem = self?.backButtonBackup
}
}
Solution 2:
Disable all accessibility on the nav bar and view controller up until viewDidAppear() is finished:
self.navigationController.navigationBar.accessibilityElementsHidden = true
self.view.accessibilityElementsHidden = true
, and then in viewDidAppear manually dispatching the layout element accessibility focused event to the label subview of UINavigationBar:
UIAccessibilityPostNotification( UIAccessibilityLayoutChangedNotification, self.navigationController.navigationBar.subviews[2].subviews[1])
// The label buried inside the nav bar. Not tested on all iOS versions.
// Alternately you can go digging for the label by checking class types.
// Then use DispatchAsync, to re-enable accessibility on the view and nav bar again...
I'm not a fan of this method either.
DispatchAsync delay in viewDidAppear seems to be needed in any case - and I think both solutions are still horrible.
I invoked UIAccessibilityScreenChangedNotification on navigation title from viewDidLoad and it worked
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
self.navigationItem.title);
First, we'll need to create an useful extension:
extension UIViewController {
func setAccessibilityFocus(in view: UIView) {
UIAccessibility.post(notification: .screenChanged, argument: view)
}
}
Then, we'll be able to set our focus in the navigation bar title like this:
setAccessibilityFocus(in: self.navigationController!.navigationBar.subviews[2].subviews[1])

hidesBottomBarWhenPushed not set when returning back to ViewController

I have the hidesBottomBarWhenPushed = true set for one of my UIViewController's (call it ViewControllerA) that is pushed onto my UINavigationController stack. I also opt to show the bottomBar when I push a new ViewController ontop of ViewControllerA. Therefore I have:
class ViewControllerA: UIViewController {
override func viewWillDisappear(animated: Bool) {
self.hidesBottomBarWhenPushed = false
}
override func viewWillAppear(animated: Bool) {
self.hidesBottomBarWhenPushed = true
}
This all works fine.
When I push ViewControllerA, the bottom bar hides.
When I push any other ViewController, the bottom bar shows.
However, when I am traveling backwards in the navigation stack (aka hitting the UIBarButtonItemBack button), I cannot get the bottomBar to hide when I pop the navigation stack to reveal ViewControllerA.
What am I missing? Thanks!
Got it! Here's what worked:
class ViewControllerCustom: UIViewController {
init() {
self.hidesBottomBarWhenPushed = true
}
override func viewDidAppear(animated: Bool) {
self.hidesBottomBarWhenPushed = false
}
}
And then in every UIViewController's custom implementation of BarButtonItemBack pressed I check to see if the previous view controller (that will be popped to needs to hide the tab bar). Granted I abstracted this out into a general function so I didn't need to repeat code, but here's the concept. Thanks for the help figuring this out though!
func barButtonItemBackPressed(button: UIButton) {
var viewControllers = self.navigationController!.viewControllers as! [UIViewController]
if ((viewControllers[viewControllers.count - 2]).isKindOfClass(ViewControllerCustom.self)) {
(viewControllers[viewControllers.count - 2] as! ViewControllerCustom).hidesBottomBarWhenPushed = true
}
self.navigationController?.popViewControllerAnimated(true)
}
I believe the intended use of this property is to hide the bar when pushed. So, when your view controller appears after the top-most one is popped, it wasn't pushed on the stack, so it doesn't change the tab bar's appearance.
This leaves you with two options:
1) Keep the bottom bar for all view controllers. When text is being entered, the keyboard covers the bottom bar.
2) Hide the bottom bar for View Controller A, as well as any other view controller that is pushed on top of A.

Disappearing UISearchController in a TableViewController that is in a UINavigationController

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
})()

UISearchController and NavigationBar back

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)
}

Resources