iOS) 노치에 따른 커스텀 상태바 만들기
커스텀 네비게이션바의 색과 상태바의 색 맞추기
- 커스텀 네비게이션을 만들게되면서 상태바와 색을 맞춰야하는 일이 생겼다. 노치에 따라 상태바에 UIView 를 얹어서 색으로 맞추는 원리로 만들었다.
iPoneSE 2세대
iOS 13.0 노치가 생긴 이후
Code
Extension 으로 UIViewController 에 함수를 추가.
extension UIViewController {
func setupStatusBar(_ color: UIColor) {
// 1.
if #available(iOS 13.0, *) {
// 2.
let margin = view.layoutMarginsGuide
let statusbarView = UIView()
statusbarView.backgroundColor = color
statusbarView.frame = CGRect.zero
view.addSubview(statusbarView)
statusbarView.translatesAutoresizingMaskIntoConstraints = false
//3
NSLayoutConstraint.activate([
statusbarView.topAnchor.constraint(equalTo: view.topAnchor),
statusbarView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1.0),
statusbarView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
// 4.
statusbarView.bottomAnchor.constraint(equalTo: margin.topAnchor)
])
// 5.
} else {
let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView
statusBar?.backgroundColor = color
}
}
}
- 1 : 노치가 있는 상태바를 지원하는 iOS 13.0 에 맞춰서 지원하도록 함.
- 2 : layoutMarginsGuide 는 여백을 나타내는 UILayoutGuide object 를 제공한다. guide 의 anchor 속성을 사용해서 constraints 를 설정할 수 있다.
Apple Developer Documentation - layoutMarginsGuide
- 3 : 애플 공식문서를 참조하면 NSLayoutAnchor 는 추가적인 type safety 를 제공한다고 한다. 잘못된 제약조건이 우연히 발생하는 것을 예방한다. (NSLayoutConstraint.Attribute 하위 클래스는 type checking 을 제공한다.) 예를들어 leadingAnchor 를 설정해주고 싶다면 파라미터에서도 leadingAnchor 에 맞춰야하는 것이다.
Apple Developer Documentation - NSLayoutAnchor
-
4 : 우리는 상태바의 높이에 따라서 커스텀 상태바를 맞춰야한다. 그래서 safe area 의 영역을 가져와야 했고 safeAreaLayoutGuide 를 포함하는 layoutMarginsGuide 의 topAnchor 을 통해 constraints 를 설정했다.
-
참고) view 의 leadingAnchor 를 다른 view 의 leftAnchor 로 constrain 한다면 두 속성 다 NSLayourXAxisAnchor 니까 compile 이 되긴한다. 하지만 Auto Layout 은 leading 과 trailing 속성을 left, right 속성과 함께 쓰는 것을 허락하지 않느다. 결과적으로 runtime 에서 crash 된다.
// 아래와 같이 사용하면 런타임 에러 발생
navigationBar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor),
- 5 : iOS 13 으로 변경됨에 따라 KVC 를 통한 접근을 금지하고 있다. 키를 가지고 접근하는 방법으로 작성하는 코드들은 iOS 13 에서 에러가 나타났다고 한다.
//searchbar 에서 textfield 를 접근하는 방법
searchBar.value(forKey: "_searchField") as? UITextField { ... }
//iOS 13 이후
let searchField = searchController.searchBar.searchTextField
하지만 iOS 13 이전에 대해서만 KVO 로써 접근하고 있는 코드이기 때문에 가능하다.