UINavigationController(화면 이동)
UINavigationController(화면 이동)
계층적 콘텐츠를 탐색하기 위한 스택기반 체계의 뷰 컨트롤러이다.
어떤 아이템을 클릭하면 상세 페이지로 넘어가면서 이전 페이지와 현재 페이지 사이의 계층이 생긴다.
UINavigationController
는 여러 개의 UIViewController
를 스택(Stack) 자료구조 형태로 관리하는 컨테이너 뷰 컨트롤러다. 내부적으로 ViewController들을 배열 형태로 관리한다.
즉,“LIFO(Last In, First Out)” 원칙(스택 자료구조와 같은 방식)으로 동작하며, 새로운 화면을 추가(push), 이전 화면을 제거(pop)하는 방식으로 작동한다.
1️⃣ Navigation Stack이란
UINavigationController
는 내부적으로ViewController
들을 배열 형태로 관리- 이 배열을 Navigation Stack이라고 부르고
viewControllers
속성으로 확인 가능
1
print(navigationController?.viewControllers ?? [])
📌 즉, Navigation Controller는
viewControllers
배열을 가지고 있으며, 새로운 화면이 push될 때 배열에 추가되고, pop될 때 제거됨!
2️⃣ Push: 새로운 ViewController를 Stack에 추가
pushViewController(_:animated:)
를 호출하면 새로운 ViewController가 스택의 맨 위에 추가됨.이전 ViewController는 사라지지 않고, 뒤에 남아 있음.
1 2
let secondVC = SecondViewController() navigationController?.pushViewController(secondVC, animated: true)
3️⃣ Pop: 현재 ViewController를 Stack에서 제거
popViewController(animated:)
를 호출하면 현재 화면이 스택에서 제거됨.- 이전 화면이 다시 나타남.
1
navigationController?.popViewController(animated: true)
4️⃣ 여러 개의 ViewController를 한 번에 Pop
- 루트 ViewController(첫 화면)까지 모두 pop하기
- 현재까지 Push된 모든 화면이 사라지고, 가장 처음 화면(루트)만 남게 됨.
1
navigationController?.popToRootViewController(animated: true)
- 특정 ViewController까지 Pop하기
- 특정 화면으로 돌아가고, 그 뒤에 있는 화면들은 전부 제거됨.
1
2
3
if let firstVC = navigationController?.viewControllers.first {
navigationController?.popToViewController(firstVC, animated: true)
}
5️⃣ Stack 직접 변경하기 (viewControllers
속성)
viewControllers
배열을 직접 변경해서 특정 화면만 남기거나, 특정 순서로 정렬 가능.
1
2
3
// 스택을 직접 변경하여 FirstVC와 ThirdVC만 남기기
navigationController?.viewControllers = [firstVC, thirdVC]
📌 즉, viewControllers 배열을 조작하면 원하는 화면만 남길 수 있음.
실행 흐름
- 앱 실행 →
FirstViewControlleer
표시됨 - “다음 화면” 버튼 클릭 →
SecondViewController
로pushViewController
(스택: [FirstViewController, SecondViewController] - “뒤로 가기”버튼 클릭 → popViewController (스택: [FirstViewController])
1. FirstViewController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import UIKit
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
title = "첫 번째 화면"
let nextButton = UIButton(type: .system)
nextButton.setTitle("다음 화면", for: .normal)
nextButton.addTarget(self, action: #selector(goToSecondVC), for: .touchUpInside)
nextButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(nextButton)
NSLayoutConstraint.activate([
nextButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
nextButton.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
@objc func goToSecondVC() {
let secondVC = SecondViewController()
navigationController?.pushViewController(secondVC, animated: true) // Push
}
}
2. SecondViewController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import UIKit
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .lightGray
title = "두 번째 화면"
let backButton = UIButton(type: .system)
backButton.setTitle("뒤로 가기", for: .normal)
backButton.addTarget(self, action: #selector(goBack), for: .touchUpInside)
let rootButton = UIButton(type: .system)
rootButton.setTitle("처음 화면으로 가기", for: .normal)
rootButton.addTarget(self, action: #selector(goToRoot), for: .touchUpInside)
let stackView = UIStackView(arrangedSubviews: [backButton, rootButton])
stackView.axis = .vertical
stackView.spacing = 10
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
@objc func goBack() {
navigationController?.popViewController(animated: true) // Pop (이전 화면으로 돌아가기)
printStack()
}
@objc func goToRoot() {
navigationController?.popToRootViewController(animated: true) // Root로 이동
printStack()
}
}
3. AppDelegate 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let navController = UINavigationController(rootViewController: FirstViewController()) // 네비게이션 컨트롤러 설정
window?.rootViewController = navController
window?.makeKeyAndVisible()
return true
}
}
This post is licensed under CC BY 4.0 by the author.