티스토리 뷰
안녕하세요 Pingu입니다!
iOS에서 개발을 하다 보면 네비게이션 컨트롤러를 자주 사용하는데요, 네비게이션 컨트롤러는 스택의 개념으로 뷰가 쌓이는데 가끔 2개나 3개를 한 번에 없애버리고 싶을 때가 있더라고요.
어떻게 하는 게 좋을까.. 하다가 다양한 방법이 있어서 정리해보려고 합니다.
물론 더 많은 방법이 있을 수 있지만... 제가 오늘까지 알아본 방법까지 정리해보겠습니다.
만약 다른 방법이 있다면 알려주시면 감사하겠습니다!
우선 프로젝트를 하나 만들고 네비게이션 컨트롤러를 만들어 줍니다.
그리고 구분이 쉽게 배경색을 RGB로 하나씩 만들어서 네비게이션 뷰 스택에 쌓는 용도로 만들어보겠습니다.
이렇게 만들어 놓으니까 은근히 예쁜데요? ㅋㅋㅋㅋ
배경 색이 없는 뷰는 WhiteViewController라고 이름 지어야겠어요.
각 뷰 마다 swift 코드로 뷰 컨트롤러 클래스를 하나씩 만들고 스토리보드에서 뷰 컨트롤러마다 지정해줍니다.
그리고 각 뷰마다 위와 같이 버튼들도 하나씩 추가했습니다.
버튼 이름에서 볼 수 있듯 적혀있는 색의 뷰로 이동하는 것이죠
지금은 White -> Red -> Blue -> Green 순으로 뷰를 쌓은 뒤 White로 바로 돌아갈 예정입니다.
@IBAction func touchUpButton(_ sender: UIButton) {
guard let redView = self.storyboard?.instantiateViewController(identifier: "redViewController") as? RedViewController else { return }
self.navigationController?.pushViewController(redView, animated: true)
}
그리고 각 뷰마다 만든 버튼에 원하는 뷰 컨트롤러를 push 하도록 액션을 만들어 주시면 됩니다.
red, blue 뷰들에도 모두 이름만 바꿔서 해주시면 됩니다!
그럼 위와 같이 스택에 뷰들이 쌓이게 됩니다. 여기서 저는 green 뷰에서는 white 뷰로 바로 나가고 싶으니 blue, red를 한 번에 pop 시키면 됩니다. 여기서 white 뷰는 네비게이션 뷰 스택에서 가장 아래있어서 Root View Controller라고 합니다.
네비게이션 뷰 컨트롤러에 존재하는 메서드들 중에
이런 애가 있는데 읽어보니 root view controller를 제외하고 모두 pop 시켜주는 메서드 같네요. 먼저 얘를 써서 green 뷰에서 white 뷰로 가보겠습니다.
@IBAction func touchUpButton(_ sender: UIButton) {
self.navigationController?.popToRootViewController(animated: true)
}
green 뷰의 버튼에 추가한 액션은 위와 같이 코딩하고 실행하면...!
잘 작동합니다. 아까 그림에서 가장 아래 있는 white view controller로 바로 이동한 것이죠!
그럼 실제로 뷰들이 어떻게 쌓여 있는지 확인해보겠습니다.
green 뷰에서 아래 코드를 작성하면 green 뷰에서 뷰들이 어떻게 쌓여있는지 알 수 있습니다.
override func viewDidLoad() {
super.viewDidLoad()
print(self.navigationController?.viewControllers)
}
아까 제가 그린대로 쌓여있는 것을 볼 수 있습니다.
이를 활용해서 원하는 뷰로 이동할 수 있는데요, 쌓인 뷰를 활용해서 똑같이 뷰를 쌓은 뒤 green에서 red로 가보겠습니다.
이때 활용할 수 있는 메서드는 popToViewController()로 지정한 뷰가 나올 때까지 pop 하는 메서드입니다.
여기서 주의할 점은 뷰 스택 안에 존재하는 객체를 사용해야 한다는 점입니다.
따라서 이번에는 green 뷰의 버튼에 아래와 같이 액션을 정의해야 합니다.
@IBAction func touchUpButton(_ sender: UIButton) {
guard let viewControllerStack = self.navigationController?.viewControllers else { return }
// 뷰 스택에서 RedViewController를 찾아서 거기까지 pop 합니다.
for viewController in viewControllerStack {
if let redView = viewController as? RedViewController {
self.navigationController?.popToViewController(redView, animated: true)
}
}
}
그러면 위와 같이 Green에서 Red로 바로 갈 수 있습니다.
이렇게 제공하는 메서드들을 사용하는 방법도 있는데, Notification을 활용하는 방법도 있습니다.
예를 들어 위와 같은 구조에서 Green 뷰에서 Red 뷰로 이동하고 싶은 경우 Blue뷰에 notification을 만들고 green 뷰를 pop 할 때 blue 뷰로 notification을 보내서 blue뷰도 함께 pop 하는 것이죠. 즉 pop 하고 싶은 뷰에게 notification을 보내서 함께 pop 시키는 건데, 한 번 해보도록 하겠습니다.
일단 Blue 뷰에 아래와 같이 Notification을 받겠다고 코드를 작성합니다.
override func viewDidLoad() {
super.viewDidLoad()
// Notification 추가
NotificationCenter.default.addObserver(self, selector: #selector(self.popBlueView), name: Notification.Name("gotoRedView"), object: nil)
}
// Notification 받으면 실행할 함수
@objc func popBlueView() {
self.navigationController?.popViewController(animated: true)
}
그리고 green 뷰에서는 blue 뷰에 notification을 보내는 함수를 하나 만들면 되는데, 저는 계속 사용하던 버튼의 액션으로 notification을 보내보겠습니다.
@IBAction func touchUpButton(_ sender: UIButton) {
// notification을 보냅니다.
self.navigationController?.popViewController(animated: true)
NotificationCenter.default.post(name: Notification.Name("gotoRedView"), object: nil)
}
위와 같이 green 뷰의 버튼에 액션을 추가하고 실행해보면..
Green 뷰에서 red로 가는 걸 볼 수 있습니다. 물론 중간에 버벅거림이 있긴 하지만 가긴 갑니다.
근데 지금은 green 뷰의 버튼을 누르면 popViewController를 한 번 더 호출했는데, 얘를 안 해주면 어떻게 될까요?
@IBAction func touchUpButton(_ sender: UIButton) {
// notification만 보냅니다.
NotificationCenter.default.post(name: Notification.Name("gotoRedView"), object: nil)
}
그러니까 위와 같이 액션을 만들면 어떻게 되냐? 는 것이죠. 바로 해보면 아래와 같이 실행됩니다.
이는 같은 네비게이션 뷰 컨트롤러에 연결된 뷰 컨트롤러들은 같은 뷰 스택을 공유하기 때문인데요, 위와 같이 코드를 작성해서 실행하면 1번만 popViewController를 호출하기 때문에 제일 위에 있던 green view만 pop 되는 것이죠.
Notification으로 네비게이션 뷰를 제어한다면 이런 점을 주의해야할 것 같습니다.
사실 그냥 네비게이션 뷰 컨트롤러에서 제공하는 메서드들을 활용하는 게 제일 깔끔한 거 같아요.
Notification을 사용하는 건 제 호기심에 해본 건데 실행도 되고 네비게이션 뷰들이 스택에 쌓이는 걸 잘 이해할 수 있는 예제라고 생각해서 함께 정리해봤습니다.
저는 이 글을 정리하면서 네비게이션 뷰에서 뷰들이 어떻게 쌓이는지 아주 잘 이해한 것 같아요!
혹시나 읽으시는 분들도 도움이 되길 바랍니다!
감사합니다!
'iOS > iOS_Memo' 카테고리의 다른 글
[iOS 앱개발] CALayer 알아보기 1 (0) | 2021.01.28 |
---|---|
[iOS 앱개발] Foreground, Background 알아보기 (0) | 2021.01.24 |
[iOS 앱개발] MPRemoteCommandCenter 사용하기 (0) | 2021.01.04 |
[iOS 앱개발] 음악이나 동영상을 백그라운드에서 재생하기 (0) | 2021.01.04 |
[iOS 앱개발] 텍스트의 특정 부분만 수정하기 - AttributedString (0) | 2020.12.25 |
- Total
- Today
- Yesterday
- 백준
- design
- DP
- 자료구조
- BFS
- 문법
- 아이폰
- 스위프트
- Swift
- Publisher
- Combine
- 코딩테스트
- IOS
- dfs
- 프로그래밍
- 코테
- Apple
- OSTEP
- 알고리즘
- document
- 테이블뷰
- OS
- System
- Xcode
- operating
- 동시성
- 앱개발
- pattern
- mac
- operator
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |