[iOS] Navigation Controller :: 스토리보드에서 화면을 전환하는 3가지 방법

2021. 2. 28. 16:11iOS

codecrafting.tistory.com/33 에서 부터 이어지는 시리즈 포스팅입니다.

 

iOS 화면전환 시리즈 프로젝트는 모두 다음과 같은 세팅이 되어있습니다.

 

1. Project Application : (iOS) App

2. Interface : Storyboard

3. Life Cycle:  UIKit App Delegate

4. Language : Swift

5. Use Core Data : 체크해제

 

시뮬레이터 iOS 버전은 14.4버전, 하드웨어는 iPhone8을 사용중입니다.  

Xcode 버전은 12.4를 사용중입니다. 하위버전으로 실습하실 경우 UI가 미묘하게 다릅니다.

 

스토리보드에서 화면을 전환하는 3가지 방법

2. 네비게이션 컨트롤러 (Navigation Controller)

 

이번에는 화면을 전환할 때 Present메소드를 사용하지 않고 '네비게이션 컨트롤러' 를 통해서 해봅시다.

네비게이션 컨트롤러는 Stack 구조로 되어있는 Container View Controller 로써 (여기 설명참조)

계층적으로 뷰를 보여주는 뷰 컨트롤러의 종류 중 하나입니다. 나머지는 직접 구현해보면서 습득해봅시다!

 

 

스토리보드 구성은 다음과 같아요

 

프레젠트 메소드 방식일 때는 첫번째 화면이 루트 뷰 컨트롤러로써 화살표가 가리켜지고 있었는데, 네비게이션 컨트롤러에서는 그렇지 않져? 왜냐면 이제부터 루트 뷰 컨트롤러는 네비게이션 컨트롤러가 될거고, 나머지 뷰 컨트롤러는 이제 구현 여부에 따라서 네비게이션 컨트롤러의 관리하에 들어갈 수 있어요. 그리고 위 캡쳐를 보면 알다시피 첫번째 화면에 네비게이션 컨트롤러에서 파생된 화살표가 가리켜지고 있어요. 이것은 네비게이션 컨트롤러의 가장 상위 화면으로 첫번째 화면을 잡을것이라는 의미겠죠?

 

그럼 네비게이션 컨트롤러 설정은 어떻게 하느냐?

제일 기본으로 주어지는 뷰 컨트롤러를 클릭하고, 상위 메뉴의 Editor - Embed In - Navigation Controller 를 차례대로 클릭해주면 대용

 

 

그럼 이제 선택한 뷰 컨트롤러를 상위로 하는 네비게이션 컨트롤러가 생성되게 되는것이지요

 

그럼 이제 본격적인 화면전환을 해야하니까 네비게이션 바(Navigation Bar) 와 네비게이션 아이템(Navigation Item)을 첫번째 화면에 추가합니다. 그리고 present 메소드로도 화면전환을 할거니까 (네비게이션 컨트롤러와 비교를 위해) 버튼하나를 만들어둡니다.

 

 

이제 첫번째 화면의 클래스를 열어서 다음과 같이 코드를 작성합시다. 

여기서도 viewDidLoad 에 딱히 코드를 작성하지 않습니다.

 

18번째 줄의 movdBynavi 메소드는 네비게이션 컨트롤러 방식의 화면전환, 29번째 줄의 movePresent는 프레젠트 방식의 화면전환 방식을 보여줍니다.

 

두번째 화면과 두번째 뷰 컨트롤러를 만들고 뷰 컨트롤러의 연결 클래스의 storyboard Id 를 SecondVC로 한 다음, 프레젠트 메소드에서 했던 것과 마찬가지로 뷰 컨트롤러의 인스턴스를 instantiateViewController 메소드를 통해서 가져옵니다.

 

guard let uvc = self.storyboard?.instanticateViewController(withIdentifier: )

가 그 메소드겠죠?

 

인스턴스를 가져왔다면 화면전환을 해야겠죠. 네비게이션 컨트롤러 방식에서 화면전환은 self.navigationController?.pushViewController 소드를 이용해 진행됩니다. UIKit.UINavigationController 에 정의되어 있는 함수로, 첫번재 인자에는 viewController 타입의 객체가, 두번째 인자에는 animated: 에 Bool 값을 넣어주면 됩니다.

 

이렇게 하면 두 번째 화면으로 전환이 완료됩니다. 그럼 되돌아가기는 어떻게 해야할까요?

이전 프레젠터 메소드 방식에서는 self.present로 화면을 전환하고 self.presentingViewController.dismiss 메소드를 사용해서 되돌아갔다면, 네비게이션 컨트롤러 방식에서는 놀랍게도 이전화면으로 돌아가는 버튼이 자동으로 생성됩니다.

 

처음에 네비게이션 컨트롤러에 대해서 설명할 때 스택구조로 되어있다고 한 것 기억나시나요?

기억절대안나죠

 

네비게이션 컨트롤러는 self.naviagtionController?.pushViewController 를 통해서 이동한 화면을 차곡차곡 스택으로 쌓아 자동으로 네비게이션 바(Navigation Bar) + 이전 화면으로 되돌아가는 버튼 을 생성해줍니다.

 

하지만 만약 이 되돌아가기 버튼을 직접 원하는 곳에 넣고 싶다면? 또 방법이 있습죠

 

11번째 줄은 dismiss, 즉 프레젠트 방식으로 되돌아가기를 구현한거고

중요한건 아래의 15번째 줄의 Back2 메소드입니다.

 

네비게이션 컨트롤러에 의해 관리되는 뷰 컨트롤러에서 사용할 수 있는데요 제가 왜 _ = 을 쓸데없이 넣었는지 모르겠지만

self.navigationController?.popViewController(animated: ) 메소드를 사용하면 이전화면으로 되돌아갈 수 있습니다.

 

이거 금방외우는 법은 navigationController은 stack 이니까 화면전환(추가) 할 때는 pushViewController, 이전화면(제거) 할 때는 popViewController 메소드인걸 생각하면 됩니다.

 

 

그럼 마지막으로 present Method 와 navigation Controller 방식 차이점을 표로 비교하고 마치겠습니다.

 

  프레젠트 메소드 네비게이션 컨트롤러
화면 전환 self.present
(_ UIViewController: , animated: )
self.presentingViewController?.dismiss
(_ UIViewController: ,animated: )
이전 화면 self.navigationController?.pushViewController
(animated: )
self.navigationController?.popViewController
(animated: )

 

 

추가적으로 찾아보니 UIViewController 에 presentedController, presentingController 가 있다고 합니다.

presentedViewController 는 자신이 호출한 뷰 컨트롤러, presentingViewController 는 자신을 호출한 뷰 컨트롤러를 가르킨다고 합니다.

 

그래서 두번째 화면에서 self.presentingViewController?.dismiss 는 사실 자기 자신을 dismiss 하라는게 아니라, 자신을 호출한 첫번째 화면의 뷰 컨트롤러에게 지금 화면전환한 (화면을 덮은) 뷰를 dismiss하라! 고 한 셈이 되네요.

 

도움이 되셧으면 제가 다 뿌듯합니다

좋아요 눌러주시죠