'Navigation and View Controller help in iOS 15 and Xcode 13

HI i have searched everywhere for a solution to my problem and cannot figure it out or found any other posts with the same problem.

I recently updated my Xcode project to Xcode 13 and my iPhone to iOS 15 and Apple made some significant changes to the navigation and tab bar structure which completely destroyed my app.

Need assistance on the correct structure on how to resolve this problem and am sure this will help lots of people who come across this same issue.

I have a ViewControllerA inside of a navigation controller which is nested inside of tab bar controller. User taps a button and segues to another ViewControllerB which is a modal VC that goes over full screen. User can then swipe down with a panGestureRecognizer. As user swipes down there is a strange flicker effect which looks awful. The only solution I found is in storyboards to completely remove navigation bar and apply constraints to top of the view(I know this is possible but not scalable as I do not want to determine device size). But then view is covered by top bar.

I have attached video showing problem.

Please help as I do not know where to go from here.

THANK YOU

var initialTouchPoint: CGPoint = CGPoint(x: 0,y: 0)

@IBOutlet weak var tableView: UITableView!


override func viewDidLoad() {
    super.viewDidLoad()
 
    tableView.dataSource = self
    tableView.delegate = self
    tableView.estimatedRowHeight = 636
    tableView.rowHeight = UITableView.automaticDimension
    
}

@IBAction func panGestureRecognizerHandler(_ sender: UIPanGestureRecognizer) {
    
    let touchPoint = sender.location(in: self.view?.window)

    if sender.state == UIGestureRecognizer.State.began {
        initialTouchPoint = touchPoint
    } else if sender.state == UIGestureRecognizer.State.changed {
        if touchPoint.y - initialTouchPoint.y > 0 {
            self.view.frame = CGRect(x: 0, y: touchPoint.y - initialTouchPoint.y, width: self.view.frame.size.width, height: self.view.frame.size.height)
        }
    } else if sender.state == UIGestureRecognizer.State.ended || sender.state == UIGestureRecognizer.State.cancelled {
        if touchPoint.y - initialTouchPoint.y > 100 {
            self.dismiss(animated: true)
        } else {
            UIView.animate(withDuration: 0.3, animations: {
                self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
            })
        }
    }
    
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = tableView.dequeueReusableCell(withIdentifier: "SwipeDownCell", for: indexPath) as! SwipeDownTableViewCell
    cell.postImageView.image = UIImage(named: "food")
    cell.postImageView.contentMode = .scaleAspectFill
    return cell
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
}

https://streamable.com/924xoo



Solution 1:[1]

I have the same issue. It is caused by a combination of safeArea and the modalPresentationStyle of the parent view controller. In my case it is UIModalPresentationOverCurrentContext. If you use other presentation styles, e.g. UIModalPresentationPopover, the flickering disappear.

As this is not appropriate in my case, I found an easy workaround. You need to set the top constraint of your first item in the child view to refer the superview, not the safe area!

enter image description here

To better support devices without the notch, you can use following helper method implemented in AppDelegate.

- (UIEdgeInsets)getSafeAreaInsets {
if (@available(iOS 11.0, *)) {
    UIEdgeInsets insets = self.window.safeAreaInsets;
    return insets;
} else {
    return UIEdgeInsetsZero;
}

Call this in the viewDidLoad of the child view and check if the bottom edge is 0.

//classic devices without notch
if ([(AppDelegate*)[[UIApplication sharedApplication] delegate] getSafeAreaInsets].bottom == 0) {
    self.labelHeaderContraint.constant = 32;
}

Sources

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

Source: Stack Overflow

Solution Source
Solution 1 napIT-Apps