탭바(tap bar)란 무엇인가?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


탭바란?

사용자가 탭바의 항목(Item)을 선택하면 해당 항목에 연결된 뷰 컨트롤러의 콘텐츠가 화면에 보이게된다. 주로 여러 메뉴를 구성할 때 많이 사용하며 카테고리 사이의 전환을 위해 사용하거나 다양한 관점으로 같은 정보를 제공하는 데 사용한다.

탭바는 화면에 보여지기 위한 뷰 요소이므로 제어를 하기 위해서는 컨트롤러가 필요하다. 프로그래머가 직접 탭바를 제어할 컨트롤러 클래스를 작성하여 사용할 수도 있지만, 대부분의 경우 프레임워크에서 제공하는 탭바 컨트롤러(UITabBarController)를 사용하여 제어한다. 이렇게 탭바와 탭바 컨트롤러를 사용하여 인터페이스를 구성한 것을 탭바 인터페이스라고 부른다.

탭바의 구조

탭바 인터페이스는 탭바 컨트롤러가 생성한 탭바 뷰(View)와 탭바 컨트롤러가 관리하는 콘텐츠 뷰 컨트롤러로 구성되어 있다. 탭바 컨트롤러는 연결된 콘텐츠 뷰 컨트롤러의 컨테이너 뷰 컨트롤러이다. 각 콘텐츠 뷰 컨트롤러는 탭바에서 하나의 탭에 해당하며, 사용자가 탭바에서 탭을 선택할 때, 탭바 컨트롤러 객체가 해당 콘텐츠 뷰 컨트롤러의 뷰를 화면에 보여준다.

탭바 인터페이스 생성하기

객체라이브러리 사용 방법

1. 탭바 컨트롤러를 객체 라이브러리로부터 드래그한다

2. 생성된 탭바 컨트롤러를 선택한 후 속성 인스펙터 탭에서 Is Initial View Controller 옵션을 선택

Is Initial View Controller 옵션은 스토리보드의 컨트롤러 중에 하나만 설정할 수 있으며, 해당 스토리보드의 맨 처음 진입화면이 된다.

이미 존재하는 뷰 컨트롤러를 탭바 컨트롤러에 연결하기

1. 기존에 있는 뷰 컨트롤러(들)를 선택하고 Editor -> Embed in -> Tab bar controller를 선택하여 뷰 컨트롤러를 탭바 컨트롤러에 포함

탭바 컨트롤러에 뷰 컨트롤러 추가하기

1. 탭바 컨트롤러에 새롭게 추가할 뷰 컨트롤러를 생성

2. 탭바 컨트롤러에서부터 키보드의 ‘control’키를 누른 상태로 드래그하여 추가할 뷰 컨트롤러에 드롭하여 세그(Segue)창이 나타나면 Relation Segue의 view controllers를 선택

3. 탭바 컨트롤러에 뷰 컨트롤러가 새롭게 추가된 것을 확인할 수 있다.

탭바 아이템이란?

탭바 뷰에서 각 탭은 이름과 이미지를 표시할 수 있고 뷰 컨트롤러는 이러한 용도로 tabBar프로퍼티를 관리한다. 탭바 컨트롤러가 콘텐츠 뷰 컨트롤러를 포함하면 해당 뷰 컨트롤러의 탭바 아이템이 탭바 컨트롤러의 탭바에 추가된다. 탭바 컨트롤러의 탭바 아이템이 6개 이상인 경우, 5번째 탭에 ‘More’이라는 아이템이 표시되고 사용자가 More 버튼을 누르면 나머지 탭 항목을 선택할 수 있는 인터페이스가 표시된다.

탭바 델리게이트

사용자가 탭바 인터페이스와 상호작용할 때, 탭바 컨트롤러 객체는 이 상호작용에 관한 알림(notification)을 델리게이트 인스턴스로 보낸다. 사용자가 탭을 선택하지 못하게 하거나, 탭을 선택한 후 추가 작업을 수행하거나, 탭 관련 사항을 모니터링하고 사용자화 하기 위해서 델리게이트를 활용한다.

UITabBarController 클래스

UITabBarController 클래스에는 탭바를 구성하고 각 탭에 해당하는 뷰 컨트롤러들을 관리하기 위한 메서드와 프로퍼티가 정의되어 있다.

탭바 컨트롤러의 탭을 구성하기 위해서는 뷰 컨트롤러를 탭바 컨트롤러의 viewControllers 프로퍼티에 할당한다. 탭바 아이템은 해당 탭에 연결된 뷰 컨트롤러를 통해 구성되며 UITabBarItem 클래스의 인스턴스를 뷰 컨트롤러의 tabBarItem 프로퍼티에 할당한다. 만약에 UITabBarItem 클래스의 인스턴스를 뷰 컨트롤러에 따로 할당하지 않을 경우, 탭바에는 이미지 없이 뷰 컨트롤러의 title 프로퍼티에 해당하는 텍스트로만 탭바의 항목으로 표시한다.

탭바 컨트롤러의 뷰

UITabBarController 클래스는 UIViewController 클래스를 상속받기 때문에 탭바컨트롤러는 view프로퍼티를 통해 접근할 수 있는 자신만의 자체 뷰(view)를 가지고 있다. 이 뷰는 탭바와 선택된 뷰 컨트롤러의 콘텐츠를 나타내는 뷰로 구성되어 있다.

  • UITabBarControler 클래스의 주요 프로퍼티 및 메서드
  • var tabBar: UITabBar: 탭바 컨트롤러와 연결된 탭바 뷰
  • var viewControllers: [UIViewController]?: 탭바 컨트롤러가 관리하는 뷰 컨트롤러의 배열! 즉, 각각의 탭바 항목에 해당하는 뷰 컨트롤러의 목록
  • func setViewControllers([UIViewController]?, animated: Bool): 탭바 컨트롤러가 관리할 뷰 컨트롤러들을 설정
  • var selectedViewController: UIViewController?: 현재 선택된 탭 항목과 연결된 뷰 컨트롤러
  • var selectedIndex: Int: 현재 선택된 탭 항목의 인덱스(index)

실습

여러개의 vc를 잡고 embed in > tabbar interface 지정해준다.

탭바 인터페이스 안에서 네비게이션 인터페이스는 가능하지만 그 반대는 안된다. 즉, 네비게이션 인터페이스 안에서 갑자기 어느 한 뷰에서 탭바를 가지고 갈 수는 없다는 것!

얼럿(alert)과 액션시트(action sheet)란 무엇인가?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


얼럿과 액션시트

UIAlertController 클래스

UIAlertController 클래스는 사용자에게 표시할 얼럿 또는 액션시트의 구성에 관한 메서드와 프로퍼티를 포함하고 있다. UIAlertController 클래스를 통해 얼럿 또는 액션시트를 구성한 후 UIViewController의 present(_:animated:completion:) 메서드를 사용하여 사용자에게 얼럿 또는 액션시트를 모달로 보여준다.

UIAlertController의 주요 메서드

  • init(title:message:preferredStyle:) > 얼럿 뷰 컨트롤러의 객체를 초기화
  • func addAction(UIAlertAction) > 얼럿이나 액션시트에 액션을 추가
  • func addTextField(configurationHandler: ((UITextField) -> Void)? = nil) > 얼럿을 통해 텍스트를 입력받고자 하는 경우 텍스트 필드를 추가

UIAlertController의 주요 프로퍼티

  • var title: String? > 얼럿의 제목
  • var message: String? > 얼럿에 대해 좀 더 자세히 설명하는 텍스트
  • var actions: [UIAlertAction] > 사용자가 얼럿 또는 액션시트에 응답하여 실행할 수 있는 액션
  • var preferredStyle: UIAlertController.Style > 얼럿 컨트롤러의 스타일로 얼럿(alert)과 액션시트(actionSheet)가 있다.

UIAlertAction 클래스

사용자가 얼럿 또는 액션시트에서 사용할 버튼과 버튼을 탭 했을 때 수행할 액션(작업)을 구성할 수 있다. UIAlertAction 클래스를 사용하여 버튼을 구성한 후 UIAlertController 객체에 추가하여 사용한다.

UIAlertAction의 주요 프로퍼티

  • var title: String? > 액션 버튼의 타이틀
  • var isEnabled: Bool > 액션이 현재 사용 가능한지를 나타냄
  • var style: UIAlertAction.Style > 액션 버튼의 적용될 스타일

UIAlertAction.Style

  • default: 액션 버튼의 기본 스타일
  • cancel: 액션 작업을 취소하거나 상태 유지를 위해 변경사항이 없을 경우 적용하는 스타일
  • destructive: 취하게 될 액션이 데이터를 변경되거나 삭제하여 돌이킬 수 없는 상황이 될 수 있음을 나타낼 때 사용하는 스타일

얼럿과 액션시트는 언제 사용할까?

얼럿

  • 중요한 액션을 하기 전 경고가 필요한 경우
  • 액션을 취소할 기회를 제공해야 하는 경우
  • 사용자의 작업을 한 번 더 확인하거나 삭제 등의 작업을 수행하거나 문제 사항을 알릴 때
  • 결정이 필요한 중요 정보를 표시할 경우

액션시트

  • 사용자가 고를 수 있는 액션 목록이 여러 개일 경우
  • 새 작업 창을 열거나, 종료 여부 확인 시
  • 사용자의 결정을 되돌리거나 그 동작이 중요하지 않을 경우

실습

import UIKit

class ViewController: UIViewController {

    @IBAction func touchUpShowAlertBtn(_ sender: UIButton) {
        // 해당 버튼을 누르면 showAlertController를 실행하게 되고
        // 스타일을 alert 스타일로 해달라고 지정
        self.showAlertController(style: UIAlertController.Style.alert)
    }

    @IBAction func touchUpShowActionSheetBtn(_ sender: UIButton) {
        self.showAlertController(style: UIAlertController.Style.actionSheet)
    }

    func showAlertController(style: UIAlertController.Style) {
        let alertController: UIAlertController
        alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: style)

        let okAction: UIAlertAction
        // handler는 alert action이 선택됐을때, OK버튼이 실행된다면
        // 실행될 코드 블럭을 의미한다
        okAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: { (action: UIAlertAction) in print("OK pressed")
        })

        let cancelAction: UIAlertAction
        // nil은 사용자가 누르면 아무 액션없이 alert이 dismiss된다
        cancelAction = UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil)

        // action을 추가해줘야 실행된다.
        // 액션 순서에 상관없이 어떻게 넣어주더라도 위치는 UIAlertController가 알아서 지정해준다
        alertController.addAction(okAction)
        alertController.addAction(cancelAction)

        // 모달로 올려줌! completion은 모달이 올라오는 애니메이션이 끝나고 직후에 호출될 블럭
        self.present(alertController, animated: true, completion: { print("Alert controller shown") })
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}

위 코드는 문제없이 진행될 것이고 이제 아래 코드를 더 추가해보자

let handler: (UIAlertAction) -> Void
        // handler라는 상수를 따로 빼놓음으로써 handler가 해야할 일을 지정해줌
        // 반복적으로 사용되는 작업은 이같이 사용하는 게 좋다
        // 어떤 응답에 대한 처리인지 써놔주었기 때문에 더 편리!
        handler = { (action: UIAlertAction) in print("action pressed \(action.title ?? "")")}

        let someAction: UIAlertAction
        someAction = UIAlertAction(title: "Some", style: UIAlertAction.Style.destructive, handler: handler)

        let anotherAction: UIAlertAction
        anotherAction = UIAlertAction(title: "Another", style: UIAlertAction.Style.cancel, handler: handler)

        alertController.addAction(someAction)
        alertController.addAction(anotherAction)

아래와 같은 에러가 뜰 것이다.

Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘UIAlertController can only have one action with a style of UIAlertActionStyleCancel’

해당 에러는 다음과 같다. 현재 위 코드에서 액션 스타일 cancel을 두번 사용하고 있는데, 다른 스타일은 상관없지만 cancel은 하나의 액션만 스타일을 사용할 수 있다. 따라서 cancel 스타일은 하나만 남겨놓고 another action의 스타일을 default로 바꾸어주고 해보자!

let anotherAction: UIAlertAction
        anotherAction = UIAlertAction(title: "Another", style: UIAlertAction.Style.default, handler: handler)

완벽하게 진행될 것이다. 추가로,,

destructive 스타일이 쓰이는 떄는 삭제를 하거나 동작을 취했을때 혹은 되돌릴 수 없을때와 같이 주의해야하는 동작을 할때 사용하는 스타일이다.

그리고 우리가 보통 앱스토어에서 로그인을 해야할때와 얼럿과 함께 텍스트필드를 사용하는 경우가 있다.

이는 아래와 같이 작성하면 된다.

alertController.addTextField(configurationHandler: { (field: UITextField) in
            field.placeholder = "플레이스 홀더"
            field.textColor = UIColor.red
        })

그런데 이 텍스트필드는 액션시트에서는 사용이 안되나보다…!

Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Text fields can only be added to an alert controller of style UIAlertControllerStyleAlert’

무언가 조금 아쉽….!

여튼! 이렇게 하면 아래와 같은 얼럿을 볼 수 있게 된다.

기본연산자 정의(Basic Operators)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


파이썬으로 처음 개발 공부를 시작했던 나에게 초반 머리에 잘 들어오지 않던 연산자 개념이 있었다. 그것은 바로 범위연산자
어떤때에는 .. 어떤때에는 … 이게 무슨의미지 헀는데, 막상 찾아보니 별거아닌(?) 개념이어서 그냥 간단하게 정리해보겠습니다 :)

기본연산자

swift에서는 통상적으로 이용하는 +, -, /, % 등과 같은 산술연산자와 $$과 같은 논리연산자 뿐만 아니라 a..<b, a…b와 같이 값의 범위를 지정할 수 있는 범위연산자를 지원한다.

  • 단항 연산자: -a, !b, c!와 같이 하나의 대상 앞뒤에 바로 붙여 사용하는 연산자
  • 이항 연산자: 2 + 3과 같이 두 대상 사이에 위치하는 연산자
  • 삼항 연산자: a? b : c 형태로 swift에 삼항연산자는 이 연산자 단 하나만 존재

할당연산자(Assignment Operators)

할당 연산자는 값을 초기화시키거나 변경 > 상수, 변수 모두에 사용 가능하다.

let a = 10
var b = 5

b = a  // b의 값은 10

let (x, y) = (1, 2)  // 튜플을 이용해 한번에 할당 가능

사칙 연산자(Arithmetic Operators)

  • 더하기, 뺴기, 곱하기, 나누기 + 나머지
1 + 2  // 3
5 - 3  // 2
2 * 3  // 6
10.0 / 2.5  //4.0
9 * 4  // 1

비교 연산자(Comparison Operators)

  • 같다 (a == b)
  • 같지 않다 (a != b)
  • 크다 (a > b)
  • 작다 (a < b)
  • 크거나 같다 (a >= b)
  • 작거나 같다 (a <= b)

삼항 조건 연산자(Ternary Conditional Operator)

삼항 조건 연산자는 question ? answer1 : answer2의 구조를 갖는다. 그래서 question 조건이 참이면 answer1, 거짓인 경우 answer2가 실행된다.

if question {
  answer1
} else {
  answer2
}

Nil 병합 연산자(Nil-Coalescing Operator)

nil 병합 연산자는 a ?? b형태를 갖는 연산자다. 옵셔널 a를 벗겨서(unwrap) 만약 a가 nildlaus b를 반환한다.

a != nil ? a! : b

즉, 옵셔널 a가 nil이 아니면 a를 unwrap하고 nil이면 b를 반환한다는 의미!

범위 연산자(Range Operators)

  • 닫힌 범위 연산자: a..b 의 형태로 범위의 시작과 끝이 있는 연산자
  • 반 닫힌 범위 연산자: a..<b의 형태로 a부터 b보다 작을때까지의 범위를 갖는 연산자 » a부터 b-1까지의 값
  • 단방향 범위: [a..] 혹은 [..a]의 형태로 범위의 시작 혹은 끝만 지정해 사용하는 연산자

논리 연산자(Logical Operators)

  • 논리부정: NOT(!a)
  • 논리 곱: AND(a&&b)
  • 논리 합: OR(a||b)

POP(Protocol Oriented Programming)프로토콜 지향 프로그래밍이란?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
참고한 블로그


POP(Protocol Oriented Programming)프로토콜 지향 프로그래밍

애플은 2015년 9월, 스위프트 버전 2.0을 발표하면서 지난 수십년간 사용된 개발 패턴이었던 객체지향 프로그래밍(OOP)가 아닌 프로토콜 지향 언어라고 발표했다고 한다. 이는 쉽게 말하자면 Class를 통한 OOP가 Struct와 Protocol을 통한 POP로 바뀌고 있다는 것을 의미한다. OOP의 핵심은 상속이다. 스위프트에서의 클래스 또한 상속이 가능하지만, 구조체나 열거형의 경우 상속이 불가능하다는 특징이 있다. 그렇기때문에 이전에는 스위프트 코드 대부분의 데이터 구조는 클래스를 통해 작성되었다. 그러나 스위프트에서 클래스와 같은 참조 타입은 단일 원본이 여기저기 참조되기 때문에 그리 권유되는 방법은 아니다. » iOS의 멀티쓰레드 참고 해당 블로그에서도 정리했듯이 클래스를 통해 기능적으로 하나의 원본을 여러군데에서 사용해야하는 경우도 있지만, 멀티쓰레드 환경에서는 한 원본을 두고 여러작업이 동시에 진행되게 되면 원본 데이터가 꼬일 가능성이 크기때문에 하나의 원본으로 작업해야할 필요가 없다면 가급적으로 값 타입인 구조체나 열거형을 사용하는 것을 권장한다.

그러다보니 현재 스위프트의 표준 라이브러리에서 타입과 관련된 것을 살펴보면 대부분이 구조체로 구현되어 있다. 그렇다면 상속도 되지 않는 구조체가 어떻게 다양한 공통 기능을 가질 수 있는 것일까?

Protocol Extension

참고할 블로그 - 프로토콜이란?

프로토콜은 이전에 정리했듯이 특정 역할을 수행하기 위한 메서드, 프로퍼티, 기타 요구사항등의 청사진이라고 할 수 있다. 예로들어 우리가 테이블뷰를 사용하려면 UITableViewDelegate 프로토콜을 채택하게 되는데, 해당 프로토콜을 채택하게 되면 우리가 필수적으로 구현해야하는 메서드가 존재한다. 즉, 우리가 프로토콜을 채택 한다면 반드시 프로토콜이 요구하는 기능을 구현하여 프로토콜을 반드시 준수 해야한다.

익스텐션은 기존 타입의 기능을 확장하는 것을 의미하는데, 한번 생각해보도록 하자.

만약 특정 프로토콜을 정의하고 여러 타입에서 프로토콜을 준수하게 만들어 타입마다 똑같은 메서드, 똑같은 프로퍼티, 똑같은 서브스크립트등을 구현해야한다고 생각해보자. 정말 많은 중독코드들이 발생하게 될 것이며, 더 나아가 유지,보수에 있어 큰 어려움을 겪게 될 것이다. 따라서 이때 필요한 것이 익스텐션과 프로토콜의 결합이다.

프로토콜 초기구현

프로토콜을 채택한 타입의 정의부에 프로토콜의 요구사항을 구현하지 않더라도 프로토콜의 익스텐션에 미리 프로토콜의 요구사항을 구현하는 것을 의미한다.

원래 프로토콜에는 기능을 수행하는 코드는 작성을 할 수 없는데, 이를 swift2 protocol extension에는 실제 값을 계산하고, 기능을 하는 메서드를 구현할 수 있게 되었다. 즉 일반 클래스처럼 프로퍼티와 메서드를 정의하는 것이 가능해짐을 의미한다. 즉 extension을 통해 protocol의 기능을 추가하는 것이 가능해지게 된 것이다.

protocol Talkable {
    var topic: String { get set }
    func talk(to: Self)
}

struct Person: Talkable {
    var topic: String
    var name: String

    func talk(to: Person) {
        print("\(topic)에 대해 \(to.name)에게 이야기합니다")
    }
}

이런식으로 Talkable이라는 프로토콜을 생성하고 Person은 이 프로토콜을 채택한다. 근데 Person 말고도 다른 타입에서도 채택하고 싶어진다면 그 타입에서도 Talkable 프로토콜이 요구하는 사항을 모두 구현해주어야 한다. 그런데 이때 프로토콜이 요구하는 사항을 미리 한꺼번에 구현해둔다면 중복되는 코드를 피할 수 있게 될 것이다.

protocol Talkable {
    var topic: String { get set }
    func talk(to: Self)
}

// 익스텐션을 사용한 프로토콜 초기 구현
extension Talkable {
    func talk(to: Self) {
        print("\(to)! \(topic)")
    }
}

이렇게 하나의 프로토콜을 만들어주고 초기구현을 해준다면 여러타입에서 해당 기능을 사용하고 싶을 때 해당 프로토콜만 채택해주면 된다. 만약 프로토콜의 초기구현과 다른 동작을 하고 싶다면, 해당 타입에 프로토콜의 요구사항을 재정의해주기만 하면 된다. 따라서 프로토콜 초기구현만 제대로 해놓는다면 여러 프로토콜을 그저 채택하기만 해도 그 타입에 기능이 추가될 수 있음을 의미한다.

프로토콜 지향 프로그래밍을 추구하는 이유

구조체, 클래스, 열거형 등 구조화된 타입 중에 상속은 클래스 타입에서만 가능하다.

클래스는 참조 타입이므로 참조 추적에 비용이 많이 발생한다. 비교적 비용이 적은 값 타입을 활용하고 싶어도, 상속을 할 수 없으므로 때마다 기능을 다시 구현해 주어야 했지만, 프로토콜 지향 프로그래밍은 그 한계를 없앴다. 즉 이를 통해 상속이 필요한 프로그램을 짤때에도 class가 아닌 struct, enum을 사용할 수 있도록 해준다.

기능의 모듈화가 더욱 명확해진다

클래스가 상속을 할 수 있도록 설계되어 있다고 하더라도 다중상속을 지원하는 언어는 많지 않다. 다중상속을 지원하지 않는다는 뜻은 하나의 상속체계에서 다른 상속체계에 속해있는 기능을 끌어다 쓸 수 없다는 뜻인데, 프로토콜 지향 프로그래밍은 기능을 프로토콜이라는 단위로 묶어 표현하고 초기 구현을 해 둘 수 있으니 상속이라는 한계점을 탈피할 수 있다. 따라서 OOP처럼 수직적인 확장구조가 아닌 수평적인 확장구조의 형태를 띄게 된다. 이는 곧 이것저것 제약없이 필요한 기능을 가져와 쓸 수 있음을 의미한다.

더 나아가 class는 모든 api에 접근이 가능한 반면 Protocol은 정의한 api만 가져오게 된다. 이는 곧 더 가볍고 보안성 높게 코드를 짤 수 있음을 의미한다.

네비게이션과 모달의 차이점은 무엇인가? +구현하는 방식

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
참고한 블로그


네비게이션과 모달

이전에 네비게이션 컨트롤러와 뷰 컨트롤러의 차이점에 대한 블로그를 작성한 적이 있다 » 블로그 참고
네비게이션과 모달 모두 뷰 컨트롤러를 제어한다는 공통점이 잇지만, 표현방식에서의 차이를 보여준다.

네비게이션 은 스택구조로 뷰를 쌓아올려 최상위 뷰만을 보여주는 형태를 말한다. 따라서 뷰를 스택에 담을때 화면에 보여주기 위해서는 push, 화면에서 제거할 때는 pop을 사용한다. 모달 은 네비게이션과 다르게 새로운 뷰를 보여주는 방식이 아닌 현재 화면을 덮는 형태를 말한다. 화면에 뷰를 보여주기 위해서 present, 화면에서 내릴때는 dismiss를 사용하는 것이 특징이다.

용도의 차이

네비게이션은 주로 정보의 깊이와 흐름을 가지는 구조에서 사용된다. 네비게이션 바 타이틀을 통해 현재 위치를 확인할 수 있으며 이전 화면으로 돌아가는 버튼 또한 네비게이션 컨트롤러에서 제공한다. 설정앱을 생각해보면 쉽게 네비게이션이 무엇인지 이해하기 쉬울 것이다. 하나의 정보 흐름을 가지고 깊게 파고드는 형식! [설정] > [Apple ID] > [이름, 전화번호, 이메일]…

반면 모달은 화면 전체를 정보의 흐름에서 벗어나 전환해주는 것을 의미한다. » 모달이란?

이전 블로그 내용을 다시 조금 정리해보자면, 모달은 사용자의 이목을 끌기위해 사용하는 화면 전환 기법을 의미한다. 이목을 집중해야하는 화면을 다른 화면 위로 띄워(present) 표현하는 방식으로 모달로 보이는 화면을 사라지게 하려면 반드시 특정 선택을 해야하는 특징을 가진다. 위에서 언급했던 것과 같이 모달은 네비게이션 인터페이스와는 달리 정보의 흐름을 가지고 화면을 이동한다기 보다는 꼭 이목을 끌어야 하는 화면에서 사용하는것이 특징이다. 되도록 단순하고 사용자가 빠르게 처리할 수 있는 내용을 표현하는 것이 좋다. [정보의 흐름이 아닌 잠깐의 팜업 혹은 잠시간의 입력폼 » 아이폰 내의 구글 메일앱]

네비게이션 구현 방식

@IBAction func signUpBtn(_ sender: UIButton) {
    let storyboard = UIStoryboard.init(name:"Main", bundle: nil)
    let viewController: SecondViewController = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
    self.navigationController?.pushViewController(viewController, animated: true)
}

모달 구현 방식

let storyboard: UIStoryboard = UIStoryboard(name: "SecondStoryboard", bundle: nil)
if let myViewController: MyViewController = storyboard.instantiateViewController(withIdentifier: "MyViewController") as? MyViewController {
	self.present(myViewController, animated: true, completion: nil)
}

구현하는 방식은 각자 조금의 차이는 있겠지만, 기본적으로 나는 위의 형식으로 구현한다.