'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
}
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!
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 |

