728x90
* Sopt 32기 앱잼을 하며 노션에 작성한 트러블 슈팅을 옮겨온 글입니다.
네비바 커스텀 장점
- 뷰 계층구조 자동 관리
- 앱 내에서 통일된 내비게이션 스타일을 유지하기 용이
- 화면 회전 및 다양한 디바이스 크기에 쉽게 대응
원래는 **UIView**에 컴포넌트를 올리는 방식으로 네비바 커스텀을 진행했었는데요, 이러한 장점이 있다는 것을 알게 된 후 기존 **UIView**에 컴포넌트를 올리는 방식이 아닌 **UINavigationBar**을 커스텀하는 방식으로 전환하게 되었습니다.
그러나 예상보다 커스텀이 가능한 범위가 제한되어 있었고, 특히 네비바의 높이를 조정하는 과정에서 네비바가 view를 가리는 이슈가 발생했습니다.
import UIKit
final class PophoryNavigationController: UINavigationController {
override func viewDidLayoutSubviews() {
configureNavigationBar()
}
override func viewDidLoad() {
super.viewDidLoad()
}
func configureNavigationBar() {
let titleFont = UIFont.head2
let titleColor = UIColor.pophoryBlack
lazy var defaultNaviBarHeight = { self.navigationBar.frame.size.height }()
let newNaviBarHeight = defaultNaviBarHeight + 22
var newFrame = self.navigationBar.frame
newFrame.size.height = newNaviBarHeight
navigationBar.frame = newFrame
let titleAttributes: [NSAttributedString.Key: Any] = [.font: titleFont, .foregroundColor: titleColor]
self.navigationBar.titleTextAttributes = titleAttributes
navigationItem.title = navigationItem.title ?? "NavTitle"
}
}
import UIKit
protocol NavigationConfigurator {
func configureNavigationBar(in viewController: UIViewController, navigationController: UINavigationController?, showRightButton: Bool, rightButtonImageType: PophoryNavigationConfigurator.RightButtonImageType?)
}
final class PophoryNavigationConfigurator: NavigationConfigurator {
static let shared = PophoryNavigationConfigurator()
enum RightButtonImageType {
case plus
case delete
case setting
}
private init() {}
func configureNavigationBar(in viewController: UIViewController, navigationController: UINavigationController? = nil, showRightButton: Bool = false, rightButtonImageType: RightButtonImageType? = nil) {
guard let navigationController = navigationController as? PophoryNavigationController else {
return
}
navigationController.configureNavigationBar()
if let rightButtonImageType = rightButtonImageType {
let rightButton: UIBarButtonItem
switch rightButtonImageType {
case .plus:
rightButton = UIBarButtonItem(image: ImageLiterals.myAlbumPlusButtonIcon, style: .plain, target: viewController, action: #selector(AlbumDetailViewController.addPhotoButtonOnClick))
case .delete:
rightButton = UIBarButtonItem(image: ImageLiterals.trashCanIcon, style: .plain, target: viewController, action: #selector(PhotoDetailViewController.deleteButtonOnClick))
case .setting:
rightButton = UIBarButtonItem(image: ImageLiterals.settingIcon, style: .plain, target: viewController, action: #selector(BaseViewController.rightButtonOnClick))
}
viewController.navigationItem.rightBarButtonItem = rightButton
viewController.navigationItem.rightBarButtonItem?.tintColor = .pophoryBlack
}
let backBarButton = UIBarButtonItem(image: ImageLiterals.backButtonIcon, style: .plain, target: viewController, action: #selector(BaseViewController.backButtonOnClick))
viewController.navigationItem.leftBarButtonItem = backBarButton
viewController.navigationItem.leftBarButtonItem?.tintColor = .pophoryBlack
let titleText = (viewController as? Navigatable)?.navigationBarTitleText ?? viewController.title ?? ""
viewController.title = titleText
}
}
익스텐션에 **UINagivationBar+statusBar의 높이를 더한 변수**를 선언했습니다.
var totalNavigationBarHeight: CGFloat {
let navigationBarHeight = navigationController?.navigationBar.frame.size.height ?? 0
let statusBarHeight = UIApplication.shared.windows.first?.windowScene?.statusBarManager?.statusBarFrame.size.height ?? 0
return navigationBarHeight + statusBarHeight
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(nameInputView)
nameInputView.snp.makeConstraints { make in
make.edges.equalTo(view.safeAreaInsets).inset(UIEdgeInsets(top: totalNavigationBarHeight, left: 0, bottom: 0, right: 0))
}
}
그러나 viewDidLayout에서 레이아웃을 설정할 경우, 설정한 navigationBar Height가 아닌 원래 뷰의 safeAreaLayoutGuide를 사용하게 됩니다. 이 문제는 멘토님의 도움으로 viewDidLayoutSubviews() 메서드에서 레이아웃 처리를 해야 설정한 마진값부터 처리된다는 것을 알게 되어 해결하게 되었습니다.
override func viewDidLayoutSubviews() {
view.addSubview(nameInputView)
nameInputView.snp.makeConstraints { make in
make.edges.equalTo(view.safeAreaInsets).inset(UIEdgeInsets(top: totalNavigationBarHeight, left: 0, bottom: 0, right: 0))
}
}
이 경험을 통해 앞으로 다른 프로젝트에서는 디자인과 애니메이션 구현 여부 등을 고려하여 적절한 설계 방식을 선택해야 함을 느꼈습니다.
'iOS > TroubleShooting' 카테고리의 다른 글
navigator area 폴더가 파란색으로 바뀐 후 xcode 내에서 파일 인식을 못하던 이슈 (1) | 2024.02.28 |
---|