02. LED 전광판 앱 (Feat. UINavigation Controller, 화면 전환)

곰주·2022년 8월 2일
2
post-thumbnail

LED 전광판 앱

처음 화면에는 LED 전광판이 표시되며, 설정 버튼을 누르면 LED 전광판에 표시하고 싶은 문구나 색상을 설정할 수 있도록 구현했다. 그리고 저장 버튼을 누르면 설정한 값이 처음 화면의 LED 전광판에 적용된다.


프로젝트 들어가기 전 알아야 할 개념들

  1. UINavigation Controller
  2. 화면 전환 방법
  3. View Controller Life Cycle
  4. 화면 간 데이터를 전달하는 방법
  5. 에셋 카탈로그 (Asset Catalog)

1. UINavigation Controller

Content View Contorller

`Content View Controller`는 화면을 구성하는 View를 직접 구현하고, 관련된 이벤트를 처리하는 View Controller이다. 일반적으로 스토리 보드 생성 시 기본으로 생성되는 View Controller라고 생각하면 된다.

Container View Controller

`Container View Controller`는 하나 이상의 `Child View Controller`(자식 뷰 컨트롤러)를 가지고 있고, 하나 이상의 `Child View Controller`를 관리하며 레이아웃과 화면 전환을 담당한다. 대표적으로 `Navigation Controller`와 `TabBar Controller`가 `Container View Controller`이다.

Navigation View Controller

이는 계층 구조로 구성된 content를 순차적으로 보여주는 `Container View Controller`이다. Navigation Controller는 `Navigation Stack`이라는 정렬된 배열을 사용하여 `Child View Controller`를 관리한다. 배열의 첫 번째 View는 `Root View Controller`이다. 스택의 가장 밑에 있다는 의미! 배열의 마지막 View는 Stack의 최상단이며, 현재 화면에 보여지고 있는 것을 의미한다. 개발자는 Segueway를 사용하거나 UINavigation Controller 메서드를 사용하여 Stack으로부터 View Controller를 추가하고 제거할 수 있다!! 사용자는 Back Button을 눌러 최상단 View Controller를 제거할 수 있으며, Left Edge Swipe 제스처를 이용하여 제거할 수 있다. 참고로! Left Edge Swipe 제스처를 사용하여 화면 전환을 하는 것은, Navigation View Controller를 이용해여 화면을 Push 하였을 때만 사용 가능하다.

잠깐!! 여기서 Navigation Stack이란 무엇인가!!
Navigation Stack은 Last-In First-Out 구조의 스택이다. 아래 사진들은 Navigation Controller로 구현되어 있는 iOS 설정 앱이다.

첫 번째 화면은 Navigation View Controller의 첫 번째 화면이므로 Root View Controller, 두 번째 화면은 Child View Controller이다. 설정 화면에서 알림을 탭하면 알림 화면이 표시되는데, 그러면 Navigation Stack에 설정 화면 위에 알림 화면이 쌓이게 된다. 이것을 Navigation Stack에 Push 하였다고 말한다. 그리고! 알림 화면에서 Back Button을 탭하면 알림 화면은 사라지고 설정 화면이 나오는데, 이것을 Navigation Stack에서 Pop 하였다고 말하는 것이다! 이처럼 Navigation Controller는 Navigation Stack을 사용하여 View Controller의 화면 전환을 관리하는 것이다!

그렇다면... Navigation Bar는 몬데?!
Navigation Controller로 구현할 때 화면 상단에 항상 보여지는 Bar! Root View Controller 외에 모든 View Controller에 Back Button이 있어 유저들이 Navigation Controller의 계층 구조에서 다시 뒤로 갈 수 있도록 해 주는 녀썩임...


2. 화면 전환 방법

iOS의 화면 전환 방법에는 크게 2가지 방법이 있다! 첫 번째로는 소스 코드를 통해 전환하는 방식, 그리고 두 번째는 StoryBoard를 통해 전환하는 방식! 이것을 또 잘게잘게 쪼개면 4가지 방법이 나온다!

1. View Controller의 View 위에 다른 View를 가져와 바꿔치는 방법
2. View Controller의 다른 View Controller를 호출하여 전환하기
3. Navigation Controller를 사용하여 전환하기
4. 화면 전환용 객체 Segueway를 사용하여 전환하기

여기서 첫 번째 방법인 "View Controller의 View 위에 다른 View를 가져와 바꿔치는 방법"은 비추!! 왜냐하면 메모리 누수 위험이 있기 때문이다! 그래서 거의 사용되지 않는다고 한다...

View Controller의 다른 View Controller를 호출하여 전환

이 방식은 현재 View Controller에서 이동할 대상의 View Controller를 직접 호출하여 화면에 표시하는 것이다. 이 방법은 기존 View Controller 위에 새로운 View Controller의 화면을 덮는 방식이다.

func present(_ viewControllerToPresent: UIViewController,aniamted flag: Bool, completion: (() -> Void? = nil)

이 present 메서드에 이동할 화면의 View Controller를 넘겨 주면, 이전 화면에서 이동할 화면의 View Controller가 표시된다. 첫 번째 파라미터에는 새로운 화면으로 이동할 화면의 View Controller의 인스턴스를, 두 번째 파라미터에는 화면 전환 시 애니메이션 효과를 줄 것인지 안 줄 것인지에 대한 Boolean 타입의 값을, 세 번째 파라미터에는 화면 전환이 끝난 후에 코드로 처리해야 할 로직을 작성하면 된다!

func dismiss(animated flag: Bool, completion: (() -> Void)? = nil)

이 dismiss 메서드는 이전 화면으로 돌아가는 메서드이다.


Navigation Controller를 사용하여 화면 전환하기

Navigation Controller계층적 성격을 띠는 컨텐츠 구조를 관리하는 컨트롤러이다. 그래서 이는 View Controller의 화면 전환을 직접 컨트롤 하고, 앱의 네이베기션 내용을 표시하는 역할을 한다고 생각하면 된다! Navigation Stack으로 Child View Controller를 관리하며, Push View Controller 메서드를 사용해서 Navigation Stack에 추가, Pop View Controller 메서드를 사용해서 Navigation Stack에서 제거한다.!! 아래 메서드 선언 방식과 함께 살펴보자! 👀


func pushViewController(_ viewController: UIViewController, animated: Bool)

Navigation Stack에 새로운 화면을 표시하는 메서드! 첫 번째 파라미터에는 새로운 화면으로 이동할 View Controller의 인스턴르를, 두 번째 파라미터에는 화면 전환이 될 때 애니메이션을 사용할 것인지 말 것인지에 대한 Boolean 타입의 값을 작성하면 된당.

func popViewController(animate: Bool) -> UIViewController?

Navigation Stack에 이전 화면으로 돌아가기 위해 현재 화면을 없애는 메서드!


화면 전환용 객체 세그웨이(Segueway)를 사용하여 화면 전환하기

`세그웨이`는 두 개의 View Controller 사이에 연결된 화면 전환 객체이다. 스토리 보드를 통해 출발지와 목적지를 직접 지정하는 방식! 세그웨이를 이용하면 직접 코드를 작성하지 않고 스토리 보드만으로 화면을 전환할 수 있다는 장점이 있단 말씀~

세그웨이에는 두 가지가 있다. 첫 번째는 Action Segueway, 두 번째는 Manual Segueway!

Action Segueway는 출발점이 Button, Cell 등과 같은 경우 Action Segueway, Trigger Segueway라고 한다. 버튼 터치와 같은 트리거 이벤트가 Segueway 실행으로 바로 연결된다. 그래서! 소스코드를 추가하지 않아도 화면 전환 기능을 구현할 수 있는 것이다!

Manual Segueway는 출발점이 View Controller 자체인 경우를 말한다.

본문 내용 관련 Code

ViewController.swift

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func tabCodePushButton(_ sender: UIButton) {
        // 우선 스토리 보드에 있는 뷰 컨트롤러를 인스턴스화 해 주어야 함.
        guard let viewController = self.storyboard?.instantiateViewController(identifier: "CodePushViewController") else { return } // Identifier => 전환할 스토리보드 아이디
        // 옵셔널로 반환하기 때문에 가드문으로 처리해야 함.
        
        self.navigationController?.pushViewController(viewController, animated: true)
        // 액션 함수 안에서 네비게이션 스택에 코드푸쉬뷰컨트롤러가 푸쉬 되게 코드 작성
        
    }
    
    @IBAction func tabCodePresentButton(_ sender: UIButton) {
        // 마찬가지로 스토리 보드에 있는 뷰 컨트롤러를 인스턴스화 해 주어야 함.
        guard let viewController = self.storyboard?.instantiateViewController(identifier: "CodePresentViewController") else { return }
        self.present(viewController, animated: true, completion: nil)
        
    }
}

SeguePushViewController.swift

import UIKit

class SeguePushViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func tapBackButton(_ sender: UIButton) {
        self.navigationController?.popViewController(animated: true)
        /*
        self.navigationController?.popToRootViewController(animated: true)  // Back Button을 눌렀을 때 네비게이션 컨트롤러의 첫 화면인 Root View Controller로 이동하게 됨. */
    }
}

SeguePresentViewController.swift

import UIKit

class SeguePresentViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func tapBackButton(_ sender: UIButton) {
        self.presentingViewController?.dismiss(animated: true, completion: nil)
    }
    
}

CodePushViewController.swift

import UIKit

class CodePushViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func tapBackButton(_ sender: UIButton) {
        self.navigationController?.popViewController(animated: true)
    }
}

CodePresentViewController.swift

import UIKit

class CodePresentViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func tabBackButton(_ sender: UIButton) {
        self.presentingViewController?.dismiss(animated: true)
    }
}

본문 내용 관련 Code의 실행 결과

profile
아기코쟁이 🧑🏻‍💻

0개의 댓글