Calculate top distance (status bar height and navigation bar height) of UIViewController without use UIApplication.shared
Usually when i develop iOS application, i need to calculate the top distance of UIViewController, this distance is sum of statusbar height and navigationbar height, the simple code you can use to do this is:
/// Get distance from top, based on status bar and navigationpublic var topDistance : CGFloat{ get{
if self.navigationController != nil &&!self.navigationController!.navigationBar.isTranslucent{
return 0
}else{
let barHeight=self.navigationController?.navigationBar.frame.height ?? 0
let statusBarHeight = UIApplication.shared.isStatusBarHidden ? CGFloat(0) : UIApplication.shared.statusBarFrame.height
return barHeight + statusBarHeight
}
}
}
If we have to use a code inside an app extension, we have this error during compile process:
“‘shared” is unavailable: Use view controller based solutions where appropriate instead
The only way to avoid this error is to calculate distance without use: UIApplication.shared, the simple idea is to add a subview in a UIViewController, constraint it to navigation bar if present and calculate the height difference, here a simple code:
extension UIViewController{
/// Calculate top distance with "navigationBar" and "statusBar" by adding a
/// subview constraint to navigationBar or to topAnchor or superview
/// - Returns: The real distance between topViewController and Bottom navigationBar
func calculateTopDistance() -> CGFloat{
/// Create view for misure
let misureView : UIView = UIView()
misureView.backgroundColor = .clear
view.addSubview(misureView)
/// Add needed constraint
misureView.translatesAutoresizingMaskIntoConstraints = false
misureView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
misureView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
misureView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
if let nav = navigationController {
misureView.topAnchor.constraint(equalTo: nav.navigationBar.bottomAnchor).isActive = true
}else{
misureView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
}
/// Force layout
view.layoutIfNeeded()
/// Calculate distance
let distance = view.frame.size.height - misureView.frame.size.height
/// Remove from superview
misureView.removeFromSuperview()
return distance
}
}
You can use it after view has been loaded, with this code:
class myClass : UIViewController{override func viewDidAppear(_ animated: Bool) {
print(self.calculateTopDistance())
}}