0
votes

Xcode 10.1, Swift 4.2

ViewController A has LargeTitles, UISearchController and UITableView in operation.

When pushing ViewController B (also a TableView) after selecting a TableViewCell, there is a delay in the space that was occupied by the UISearchBar being removed as shown in the animation.

ViewController B also has a UISearchController, but as per usual behaviour, is hidden until the user drags down on the screen.

Does anyone know how to prevent this from happening?

enter image description here

Additional Information & Code:

ViewController A When cell tapped, it pushes ViewController B using a Show (e.g Push) segue on Storyboard with Animates selected. Data is injected using the prepareForSegue method.

performSegue(withIdentifier: "showLogbook", sender: self)

ViewController B:

class LogbookVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UISearchResultsUpdating {

    //Extract
    private let searchController = UISearchController(searchResultsController: nil)


    @IBOutlet private var addButton: UIBarButtonItem!
    @IBOutlet private var shareButton: UIBarButtonItem!
    @IBOutlet private var backButton: UIBarButtonItem!
    @IBOutlet private var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self
        tableView.rowHeight = 75.0
        //loading tableView data
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationController?.navigationBar.prefersLargeTitles = true
    self.definesPresentationContext = true
    configureSearchController()
    fetchAndSortLogEntries()
}

private func configureSearchController() {
    navigationItem.searchController = searchController
    searchController.searchResultsUpdater = self
    searchController.searchBar.scopeButtonTitles = ["Newest", "Oldest"]
    searchController.searchBar.delegate = self
    searchController.searchBar.barStyle = .black
    searchController.searchBar.tintColor = K.Colors.appMid
    searchController.searchBar.keyboardAppearance = .dark
    searchController.searchBar.returnKeyType = .done
    searchController.dimsBackgroundDuringPresentation = false
    let attributes = [NSAttributedString.Key.foregroundColor: K.Colors.appMid]
    UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes(attributes, for: .normal)
    searchController.searchBar.setValue("Reset", forKey: "_cancelButtonText")
    let searchBarCancelButton = searchController.searchBar.value(forKey: "cancelButton") as? UIButton
    searchBarCancelButton?.setTitle("Reset", for: .normal)
}
1
Can you show us how you're presenting ViewControllerB from A?Alex Ioja-Yang
I'm guessing the problem is entirely in the second view controller. Are you sure the search bar is initially hidden and not hidden in viewDidAppear for example?devios1
Updated with some code, thanks for taking a look.rbaldwin
If I do not configure the searchController in ViewController B then the TableView presents correctly, so the issue is there somewhere. Commenting out various lines in configureSearchController makes no difference, the problem is still present. I will create a basic test project and see if I can recreate the problem there.rbaldwin

1 Answers

0
votes

I think this is a bug when using LargeTitles and having two UISearchControllers in adjacent ViewControllers.

I found that by adding the UISearchController to the NavigationItem in viewDidAppear fixes the issue, however it has to be added asynchronously otherwise the following fatal error occurs:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Only one palette with a top boundary edge can be active outside of a transition.

This code needs to be added to both ViewControllers, so that the problem behaviour is also prevented when navigating back to ViewController A.

Xcode 10.1, Swift 4.2

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        DispatchQueue.main.async {
            self.navigationItem.searchController = self.searchController
            self.searchController.searchResultsUpdater = self
            self.searchController.searchBar.delegate = self
        }
    }

This code will ensure the NavigationBar is not hidden when the next ViewController appears:

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.isNavigationBarHidden = false
    }

enter image description here