Calculate top distance (status bar height and navigation bar height) of UIViewController without use UIApplication.shared

Luca Becchetti
2 min readOct 17, 2017

--

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())
}
}

--

--

Luca Becchetti
Luca Becchetti

Written by Luca Becchetti

I am a professional programmer with a background in software design and development, currently developing my qualitative skills on a startup company “Frind”

Responses (2)