'Tableview y origin not animating properly when navigationItem.titleView is hidden (Swift 5)

I’m trying to get the tableView to move up when the search bar does. Take a look at the problem:

enter image description here

I think I see what the issue is here, but I can't think of a solution. In SearchResultsUpdating I have an animation block:

func updateSearchResults(for searchController: UISearchController) {

    UIView.animateKeyframes(withDuration: 1, delay: 0, options: UIView.KeyframeAnimationOptions(rawValue: 7)) {

    self.tableView.frame = CGRect(x: 20, y: self.view.safeAreaInsets.top, width: 
    self.view.frame.size.width-40, height: self.view.frame.size.height - 
    self.view.safeAreaInsets.top)

    }
}

It seems to me that the animation block is only receiving the previous coordinates for the y origin, hence it is animating out of sync. I tried adding a target to the tableView, or navigationBar, or the searchBarTextField instead, but nothing worked.

Any help is appreciated, thanks!

EDIT: After implementing Shawn's second suggestion this was the result:

enter image description here

I can't imagine why it isn't animating smoothly now... very frustrating!

EDIT 2 - Requested Code:

class ViewController: UIViewController{

//City TableView
let cityTableView = UITableView()

let searchVC: UISearchController = {
    let searchController = UISearchController(searchResultsController: nil)
    searchController.obscuresBackgroundDuringPresentation = true
    searchController.searchBar.placeholder = "Search"
        return searchController
    }()

//viewDidLoad
override func viewDidLoad() {
    super.viewDidLoad()

    //Do any setup for the view controller here
    setupViews()
    
    //CityViewController
    setupCityViewTableView()
    
}

//setupViews
func setupViews(){
    //NAVIGATIONBAR:
    //title
    title = "Weather"
    //set to hidden because on initial load there is a scroll view layered over top of the CityViewTableView (code not shown here). This gets set to false when the scrollView alpha is set to 0 and the CityViewTableView is revealed
    navigationController?.navigationBar.isHidden = true
    navigationController?.navigationBar.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
    
    //NAVIGATION ITEM:
    navigationItem.searchController = searchVC
    
    //UISEARCHBARCONTROLLER:
    searchVC.searchResultsUpdater = self
    }
}

//MARK:  -CityViewController Functions
extension ViewController{

//setUp TableView
func setupCityViewTableView(){
    
    cityTableView.translatesAutoresizingMaskIntoConstraints = false
    //set tableView delegate and dataSource
    cityTableView.delegate = self
    cityTableView.dataSource = self
    //background color
    cityTableView.backgroundColor = .black
    //separator color
    cityTableView.separatorColor = .clear
    //is transparent on initial load
    cityTableView.alpha = 0
    //set tag
    cityTableView.tag = 1000
    //hide scroll indicator
    cityTableView.showsVerticalScrollIndicator = false
    //register generic cell
    cityTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cityCell")
    //add subview
    view.addSubview(cityTableView)
    //Auto Layout
    cityTableView.leadingAnchor
        .constraint(equalTo: view.leadingAnchor,
                    constant: 20).isActive = true

    cityTableView.topAnchor
        .constraint(equalTo: view.topAnchor,
                    constant: 0).isActive = true

    cityTableView.trailingAnchor
        .constraint(equalTo: view.trailingAnchor,
                    constant: -20).isActive = true

    cityTableView.bottomAnchor
        .constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor,
                    constant: 0).isActive = true
    
    }
}

//MARK: -TableView Controller
extension ViewController: UITableViewDelegate, 
UITableViewDataSource{

//number of rows
func tableView(_ tableView: UITableView, numberOfRowsInSection 
section: Int) -> Int {
    
    if tableView.tag == 1000{
        return 5
    }
    return self.models[tableView.tag].count
    
}

//cell for row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: 
IndexPath) -> UITableViewCell {
    
    //CityViewController
    if tableView.tag == 1000{
        
        let cell = tableView.dequeueReusableCell(withIdentifier: 
"cityCell", for: indexPath)
        cell.textLabel?.text = "Test"
        cell.textLabel?.textAlignment = .center
        cell.backgroundColor = .systemGray
        cell.selectionStyle = .none
        cell.layer.cornerRadius = 30
        cell.layer.borderColor = UIColor.black.cgColor
        cell.layer.borderWidth = 5
        cell.layer.cornerCurve = .continuous

        return cell
    }
    
    //WeatherViewController
    //code here for scrollView tableViews
}

//Height for row
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if tableView.tag == 1000{
        return view.frame.size.height/7
    }
    return view.frame.size.height/10
}

//Should Highlight Row
func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
    if tableView.tag == 1000{
        return true
    }
    return false
}

//Did select row
func tableView(_ tableView: UITableView, didSelectRowAt 
indexPath: IndexPath) {
    
    //calls function for segue to Weather Scroll View (not shown)
    if tableView.tag == 1000{
        segueToWeatherView(indexPath: indexPath)
        
        }
    
    }

}

EDIT 3: When I comment out another function it finally works, but I'm not sure exactly why, or how to fix it. This is the function in question, addSubViews()

//setup viewController
func addSubViews(){
    //add weatherView as subView of ViewController
    view.addSubview(weatherView)
    //add subviews to weatherView
    weatherView.addSubview(scrollView)
    weatherView.addSubview(pageControl)
    weatherView.addSubview(segueToCityViewButton)
    weatherView.addSubview(segueToMapViewButton)
    
}

Specifically, it works when I comment out this line:

view.addSubview(weatherView)

Here is all the code concerning the setting up of the weatherView and all of its subViews:

//Any additional setup goes here
private func setupViews(){
    
    //VIEWCONTROLLER:
    //title
    title = "Weather"
    //Background color of view Controller
    view.backgroundColor = .darkGray
    
    //WEATHERVIEW:
    //Background color of weather view Controller
    weatherView.backgroundColor = .clear
    //weatherView frame
    weatherView.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height)
    
    //SCROLLVIEW:
    //background color of scroll view
    scrollView.backgroundColor = .clear
    //scrollView frame
    scrollView.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height)
    //changed
    
    //PAGECONTROL:
    //page control frame
    pageControl.frame = CGRect(x: 0, y: view.frame.height-view.frame.size.height/14, width: view.frame.width, height: view.frame.size.height/14)
    
    //TRANSITIONVIEW:
    //TransitionView frame
    transitionView.frame = CGRect(x: 20, y: 0, width: view.frame.size.width-40, height: view.frame.size.height)
    
    //BUTTONS:
    //segue to CityView
    segueToCityViewButton.frame = CGRect(x: (weatherView.frame.width/5*4)-20, y: weatherView.frame.height-weatherView.frame.size.height/14, width: weatherView.frame.width/5, height: pageControl.frame.height)
    //segue to MapView:
    segueToMapViewButton.frame = CGRect(x: 20, y: weatherView.frame.height-weatherView.frame.size.height/14, width: weatherView.frame.width/5, height: pageControl.frame.height)
    
    //LABELS:
    transitionViewLabel.frame = transitionView.bounds
    
    //NAVIGATIONBAR:
    //set to hidden on initial load
    navigationController?.navigationBar.isHidden = true
    navigationController?.navigationBar.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
    
    //NAVIGATION ITEM:
    navigationItem.searchController = searchVC
    
    //UISEARCHBARCONTROLLER:
    searchVC.searchResultsUpdater = self
    
    
}

For the sake of being thorough, here is the full viewDidLoad() Function:

override func viewDidLoad() {
    super.viewDidLoad()

    //MARK: View Controller
    
    //These two will eventually be moved to the DispatchQueue in APICalls.swift
    configureScrollView()
    pageControl.numberOfPages = models.count
    
    
    //Do any setup for the view controller here
    setupViews()
    
    //setup ViewController
    addSubViews()

    //Add Target for the pageControl
    addTargetForPageControl()
    
    //MARK: CityViewController
    setupCityViewTableViews()
    
}

EDIT 4: With the following changes in viewDidLoad(), I finally got it to work!

override func viewDidLoad() {
super.viewDidLoad()

//MARK: CityViewController
//Moved to a position before setting up the other views
setupCityViewTableViews()

//MARK: View Controller

//These two will eventually be moved to the DispatchQueue in APICalls.swift
configureScrollView()
pageControl.numberOfPages = models.count

//Do any setup for the view controller here
setupViews()

//setup ViewController
addSubViews()

//Add Target for the pageControl
addTargetForPageControl()

}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source