안녕하세요!
UINavigationController에 이어서
UINavigationBar 커스텀하기에 대해 알아보려고 합니다
틀린 내용과 오역이 있을 수도 있으니... 많은 피드백 부탁드려요!!
작년에 스터디와 프로젝트들을 하면서 내비게이션 바를 커스텀할 일이 많았는데요 그때마다 겨우겨우 해결했던 기억이 있어서... 드디어 정리를 해보려고 합니다! 커스텀하는 방법을 알아보기 전 내비게이션 바에 대해서 먼저 알아보도록 하겠습니다!
이전 포스팅에도 작성했지만 한번 더 살펴보도록 하죠!
참고자료
https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621873-viewcontrollers
https://developer.apple.com/documentation/uikit/uinavigationbar

A UINavigationBar object is a bar, typically displayed at the top of the window, containing buttons for navigating within a hierarchy of screens. The primary components are a left (back) button, a center title, and an optional right button. You can use a navigation bar as a standalone object or in conjunction with a navigation controller object.
A navigation bar is most commonly used within a navigation controller. The UINavigationController object creates, displays, and manages its associated navigation bar, and uses attributes of the view controllers you add to control the content displayed in the navigation bar.
내비게이션 바 object는 윈도우 상단에 표시되는 바로서, 화면 계층구조에서 탐색을 위한 버튼을 포함한다. 주요 컴포넌트는 left (back) 버튼, 중앙의 타이틀, optional 한 오른쪽 버튼이다. 내비게이션 바는 독립적인 객체로(Navigation Controller 없이) 사용하거나 내비게이션 컨트롤러 객체와 함께 사용할 수 있다.
내비게이션 바는 대부분 내비게이션 컨트롤러와 함께 사용된다. UINavigationController 객체는 연결된 내비게이션 바를 만들고 표시하고 관리한다. 그리고 내비게이션 바에 표시되는 콘텐츠들을 제어하기 위해 추가한 뷰 컨트롤러의 속성을 사용한다.
공식문서에 아주 설명이 잘 되어 있네요
그럼 좀 더 자세히 알아보도록 합시다!
내비게이션 컨트롤러를 사용한다면 이 놈이 내비게이션 바를 자동으로 만들고 내비게이션 아이템들을 적절한 때에 푸시와 팝을 합니다.
내비게이션 컨트롤러는 뷰 컨트롤러들을 탐색할 때 해당 뷰 컨트롤러의 navigationItem 프로퍼티를 사용해 네비바에 표시될 내용을 결정하는데요.
기본적으로는 뷰컨의 title을 네비바에 표시하지만 navigationItem을 커스텀하여 네비바의 내용을 변경할 수 있습니다!
또한 내비게이션 컨트롤러는 자동으로 내비게이션바 객체의 대리자(delegate) 로서 자기 자신을 할당하는데요.
따라서 공식문서에서는 내비게이션 컨트롤러를 사용할 때
네비바에 커스텀 델리게이트 객체를 할당하지 말 것 을 명시하고 있습니다!
보통은 네비게이션 바를 네비게이션 컨트롤러와 함께 사용하지만
네비게이션 바 UI를 사용해 컨텐츠 내비게이션에 대한 자체적인 접근 방식을 구현해야 되는 상황에서 독립적으로 사용하면 되겠죠?
내비게이션 컨트롤러와 함께 사용할 때는 내비게이션 컨트롤러가 내비게이션 바를 자동으로 만든다고 했는데요
그럼 내비게이션 컨트롤러 없이 사용할 때는 내비게이션 바를 직접 구성해야 합니다!
따라서 내비게이션 아이템들을 직접 추가해줘야 하는데
이때, addSubview() 메서드를 사용하는 것이 아니라 UINavigationItem 프로퍼티에 UIBarButtonItem을 할당해
내비게이션 바 컴포넌트들을 구성해야 합니다!
코드를 한 번 보시죠!
import UIKit
final class ViewController: UIViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
configureNaviBarSetting()
}
}
extension BrowseStyleViewController {
private func configureNaviBarSetting() {
//
let leftBarButton = UIBarButtonItem(
title: "",
style: .plain,
target: self,
action: nil
)
navigationItem.title = "타이틀"
navigationItem.leftBarButtonItem = leftBarButton
}
}
공식문서에서 내비게이션바는 UINavigationItem 객체의 스택을 관리한다고 되어있길래
네비게이션 아이템의 스택이 뭐지..? 했는데요
일단 일반적인 상황인 네비게이션 컨트롤러와 네비바를 함께 사용한다고 가정해 봅시다.
그러면 화면전환이 일어나고 그에 따라 내비게이션 바의 아이템들이 계속 변하겠죠?
화면마다 navigationBarItem들을 저장하는 자료구조가 필요하게 됩니다.
이때 UINavigationBar의 items라는 스택이 사용됩니다!
공식문서의 그림이 잘 이해가 가지 않아 정리를 해보았는데요

items : UINavigationItem 객체의 배열이고 viewController들을 담고 있는 navigationStack처럼
각 뷰컨의 navigationItem을 담고 있는 배열이라고 생각하시면 됩니다!
그리고 push, pop 메서드를 통해 스택으로 사용됩니다!!
topItem : items 스택의 최상위 UINavigationItem입니다.
간단히 말하면 현재 화면에 해당하는 내비게이션 컨트롤러의 navigationItem 객체가 되겠죠?
backItem : topItem 바로 아래에 위치한 UINavigationItem입니다.
간단히 말하면 바로 직전 화면에 해당하는 내비게이션 컨트롤러의 navigationItem 객체입니다!
아이템을 push 하고 pop 하는 것 외에도, items 속성이나 setItems(_:animted:) 메서드를 통해서
스택의 컨텐츠들을 설정할 수 있습니다.
navigationBar를 navigationController와 같이 사용할 때에는 커스텀 델리게이트 객체를 할당하면 안 된다고 했었는데요.
navigationBar를 독립적인 객체로 사용한다면 커스텀 델리게이트 객체를 할당할 수 있습니다!
따라서 델리게이트 notification이 내비게이션 아이템이 푸쉬 팝 될 때를 알려주게 됩니다.
UINavigationItem
title, leftBarButtonItem(s), rightBarButtonItem(s), 프롬프트 등의 속성을 가짐.UINavigationItem 객체는 하나의 화면(viewController)에 대응됨. 각각의 뷰 컨트롤러는 자신의 내비게이션 아이템을 가지고 있으며, 뷰 컨트롤러가 내비게이션 스택에 push, pop 될 때 해당 네비바에 표시되거나 사라짐.navigationItem 프로퍼티를 통해 접근하고, 내비게이션 바에 표시하고자 하는 내용(제목, 버튼 등)을 설정 가능.UIBarButtonItem
요약
UINavigationItem은 네비바의 구성 요소를 정의하는 객체, 특정 뷰컨의 네비바 내용을 관리하는 컨테이너 역할UIBarButtonItem은 유저가 사용할 수 있는 버튼, UINavigationItem에 할당되어 네비바에 표시됨, UINavigationItem의 내용물!따라서 위의 2. 내비게이션 컨트롤러와 내비게이션바를 함께 사용할 때에서 작성한 코드처럼
UINavigationItem.leftBarButton에 UIBarButtonItem을 넣는 것입니다!
backBarButtonItem
leftBarButtonItem
요약
backBarButtonItem은 현재 화면이 아니라 다음 화면의 뒤로 가기 버튼의 스타일을 커스터마이즈 할 때 사용되며, 주로 버튼의 제목이나 스타일 변경에 사용됩니다!leftBarButtonItem 현재 화면의 내비게이션 바의 왼쪽 상단 버튼.UINavigationController에 이어 UINavigationBar도 알아보았는데요.
다음 포스팅은 UINavigationBar 커스텀하는 방법에 대해 알아보겠습니다!
프로젝트할 때 대충 사용할 줄 만 알고 내부 구조나 원리는 이해하지 못했었는데
이번에 공식문서 보면서 공부하니 개념이 확실히 잡히고 커스텀하기 더 수월해질 것 같습니다!
공식문서 리뷰를 계속 이어나가기를 목표로 하며...! 포스팅 마치겠습니다~
주의사항 정리
네비바를 내비게이션컨트롤러와 함께 사용할 때는 커스텀 델리게이트 객체 할당하지 말기