NavigationCotroller는 왜 사용할까?
애플 공식문서를 확인해보면 이미지로 한눈에 알 수 있다.
밑에 이미지 처럼 View들의 계층을 Stack구조로 관리 할 수 있게된다. 즉 선입후출 구조로 View들이 계층일 이루게 해주는 역할을 한다. `NavigationCotroller`을 적용한다면 View들은 애플이 친절하게 이미 구현해 놓은 강력한 기능들을 사용 할 수 있다.
애플 공식문서에 나온 NavigationController 특징 요약
- UINavigationController는 하나 이상의 뷰 컨트롤러를 관리하는 컨테이너 뷰 컨트롤러이며.
이 인터페이스에서는 한 번에 하나의 뷰 컨트롤러만 표시됨. - 뷰 컨트롤러는 순서가 있는 배열(네비게이션 스택)을 통해 관리되며 배열의 첫 번째 뷰 컨트롤러는 루트 뷰 컨트롤러이고, 마지막 뷰 컨트롤러는 현재 표시되고 있는 최상위 항목(선입후출 구조)
- NavigationBar를 자동으로 적용시킴(NavigationCotroller를 사용시 얻는 큰 이점중 하나) NavigationBar는 왼쪽(뒤로 가기), 중앙(타이틀), 오른쪽(추가 액션) 세 부분으로 업데이트됨
- ModalPresent사용 가능
사용방법
사용 예시를 들기 위해 아래와같이 storyboard를 셋팅해줬고 시나리오는 다음과 같다.
1. 왼쪽부터 첫번째 ViewController에서 버튼 클릭
2. 두번째 ViewController로 이동
3. 두번째 ViewController에서 버튼 클릭
4. ModalPresnet(모달이 튀어나옴)
NavigationController 적용 방법
1. 적용시키고 싶은 ViewController를 클릭
2. 상단 메뉴에서 Editor > Embed in > Navigation Controller
3. - 끝 -
첫번째 ViewController
알 수 있는점
1. navigationItem.title에 String을 할당하는 것만으로도 간단하게 구현이 가능
2. guard let 바인딩을 사용해 secondVC라는 storyboardID를 갖고 있는 ViewController를 인스턴스화 시켜줌
3. 인스턴스화된 viewController를 사용해 pushView메서드에서 활용(화면이동)
여기서 알 수 있는 가정 큰 점은 NavigationItem 구현에 필요한 어떠한 코드를 작성하지 않았지만 NavigationCotroller를 사용해 이미 구현되어있는 NavigationItem에 점하나 찍고 간단하게 원하는 내용으로 수정할 수 있다
navigationItem.title = "첫번째화면"
class ViewController: UIViewController {
@IBOutlet weak var uilabel: UILabel!
@IBOutlet weak var goSecondVCButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
goSecondVCButton.setTitle("SecondVC가기", for: .normal)
navigationItem.title = "첫번째화면"
}
@IBAction func goSecondVCTapped(_ sender: UIButton) {
//instantiateViewController메서드는 스토리보드 파일에 있는 뷰 컨트롤러 인스턴스를 생성하고 초기화시킴
guard let viewController = self.storyboard?.instantiateViewController(withIdentifier: "secondVC") else { return }
self.navigationController?.pushViewController(viewController, animated: true)
}
}
두번째 ViewController
알 수 있는점
1. 첫번째 View의 navigationItem.title이 적힌 뒤로가기 버튼이 자동으로 삽입되어있다.
2. stack의 구조로 View들이 자동으로 정리됨
3. Modal은 push가 아닌 present로 호출한다.
여기서 알 수 있는 가정 큰 점은 navigationItem 구현에 필요한 어떠한 코드를 작성하지 않았지만 NavigationCotroller를 채용함으로서 간단하게 구현이 가능하다
class SecondVC: UIViewController {
@IBOutlet weak var secondVCButton: UIButton!
@IBOutlet weak var goToMainVC:UIButton!
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "SecondVC"
secondVCButton.setTitle("나와라 모달!", for:.normal)
}
@IBAction func goToMainVCButtonTapped(_ sender: UIButton) {
guard let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondVCModal")
else { return }
//네비게이션 컨트롤러의 프레젠테이션 스타일을 설정
self.navigationController?.modalPresentationStyle = .popover
self.navigationController?.present(secondViewController, animated: true)
}
}
모달 ViewController
모달은 기본적으로 NavigationBar를 제공해주지 않는다
class secondVCModal: UIViewController {
@IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label.text = "두번째뷰 모달 나왔다"
}
}
만약 모달에도 버튼을 달고 싶다면 다음과 같이 하면 된다.
class ModalViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// '닫기' 버튼 생성
let closeButton = UIBarButtonItem(title: "닫기", style: .plain, target: self, action: #selector(closeModal))
self.navigationItem.leftBarButtonItem = closeButton
}
@objc func closeModal() {
// 모달 뷰 컨트롤러 닫기
self.dismiss(animated: true, completion: nil)
}
}
Modal / Push 어떤것을 사용하는게 좋을까? 🤔
Modal Presentation
- 형태: 모달(Modal) 전환은 주로 사용자에게 중요한 작업을 수행하도록 요구할 때 사용됩니다
(예: 설정 변경, 로그인, 정보 입력, ).
- 스택 관계: 모달 뷰는 현재의 네비게이션 스택과는 독립적으로 표시됩니다. 즉, 새로운 뷰 컨트롤러가 현재 화면 위에 오버레이되는 형식
- 표현 방식: 모달은 전체 화면, 부분 화면, 팝오버 등 다양한 스타일로 표현 가능
쇼핑을 하다보면 모달을 많이 볼 수 있는데 화면 밑에서 위로 [쿠폰 발행]하면서 뜨는 모달로 구현된 페이지들을 볼 수 있다.즉 사용자의 정보 흐름을 방해하지 않으면서 연관성은 없지만 높은 집중도를 주는 페이지를 할 때 modal이 적합!
‼️애플 공식문서에 나오는 모달을 사용 시 주의점은 다음과 같다.
- 명확한 이점이 있을 때만 모달 뷰 사용
- 모달 작업을 간단하고 직관적으로 유지
- 모달 경험이 앱 내의 별도 앱처럼 느껴지지 않도록 주의
- 복잡한 작업이나 내용에 대해 전체 화면 모달 스타일 고려
- 모달 뷰를 명확하게 종료할 수 있는 방법 제공
- 데이터 손실 방지를 위한 확인 절차 제공
- 모달 뷰의 작업을 쉽게 식별할 수 있도록 명확한 제목 제공
- 다른 모달 뷰를 표시하기 전에 현재 모달 뷰를 닫을 수 있게 함
- 여러 모달 뷰를 동시에 표시하지 않도록 주의
Push Navigation
- 형태: 푸시(Push) 전환은 주로 계층적인 데이터 구조를 탐색할 때 사용됩니다
(예: 이메일 목록에서 개별 이메일을 열기, 애플기기 설정앱)
- 스택 관계: 푸시는 UINavigationController의 스택에 뷰 컨트롤러를 추가한다. 이전 화면으로 돌아갈 수 있는 '뒤로 가기' 버튼이 자동으로 제공
- 표현 방식: 새로운 뷰 컨트롤러가 오른쪽에서 왼쪽으로 슬라이드되며 현재 화면을 대체
- 네비게이션 스택: 새로운 뷰 컨트롤러가 네비게이션 스택에 추가되며, 사용자가 '뒤로 가기'를 누르면 스택에서 제거
- 선입후출 구조
NavigationItem이나 버튼은 커스텀이 가능하다.
// 네비게이션 바의 타이틀 설정
self.navigationItem.title = "새로운 타이틀"
// 네비게이션 바 왼쪽에 커스텀 버튼 추가
let leftButton = UIBarButtonItem(title: "왼쪽 버튼", style: .plain, target: self, action: #selector(leftButtonTapped))
self.navigationItem.leftBarButtonItem = leftButton
// 네비게이션 바 오른쪽에 커스텀 버튼 추가
let rightButton = UIBarButtonItem(title: "오른쪽 버튼", style: .plain, target: self, action: #selector(rightButtonTapped))
self.navigationItem.rightBarButtonItem = rightButton
마무리 및 요약
UINavigationController는 앱 내에서 여러 뷰 컨트롤러들을 계층적으로 관리하면서 사용자의 탐색 경험을 간편하고 직관적으로 만들어줍니다. 특히, 네비게이션 스택을 이용한 선입후출 구조는 뷰 컨트롤러 간의 전환을 체계적으로 관리할 수 있게 해주며, 내장된 네비게이션 바를 통해 애플의 HIG에 적합한 디자인을 구현할 수 있습니다.
- 계층적 뷰 관리: UINavigationController는 여러 뷰 컨트롤러들을 계층적으로 관리 사용자의 탐색 경험을 간소화하고 직관적으로 만듬
- 네비게이션 스택 활용: 네비게이션 스택을 사용하는 선입후출 구조를 통해, 뷰 컨트롤러 간의 전환을 효율적으로 관리
- 내장된 네비게이션 바: 자동으로 적용되는 네비게이션 바를 통해, 사용자 인터페이스를 사용자 친화적이고 직관적으로 만듬
- 모달과 푸시 전환의 이해: 모달과 푸시 전환의 차이점을 이해하고 적절한 상황에서 이들을 활용함으로써, 사용자에게 최적화된 탐색 경험을 제공
- 커스터마이징 기능: UINavigationController의 다양한 커스터마이징 옵션을 활용하여 앱의 브랜딩과 사용자 경험을 향상
- UINavigationController의 이러한 특징들을 잘 활용함으로써, 앱의 사용성과 전체적인 품질을 높이는 것이 가능합니다. 개발자들에게는 이러한 기능들을 숙지하고 적절하게 적용하는 것이 중요한 역할
참고자료
https://developer.apple.com/design/human-interface-guidelines/modality
https://developer.apple.com/documentation/uikit/uinavigationcontroller
'🍎swift' 카테고리의 다른 글
URLRequestBuilder만들기 .. feat 리팩토링 (0) | 2024.04.02 |
---|---|
TLI - Concurrency (0) | 2024.01.17 |
제어 흐름 (Control Flow) (0) | 2023.11.21 |
text field 바꾸기 (플레이스 홀더, 클리어 버튼) (0) | 2023.04.21 |
[Swift] 연산자 커스텀 타입 (0) | 2023.04.05 |