부스트코스 “iOS 프로그래밍” 요약정리 - 2. 회원가입 화면 구현 #0 ~ #2

Updated:




#0. 파트 개요

프로젝트 개요

  • 오토 레이아웃과 다양한 UI 컴포넌트를 활용하여 회원가입 절차를 위한 화면과 기능을 구성한다.
  • 네비게이션 인터페이스와 모달을 활용하여 화면전환을 해본다.

프로젝트 목적

  • 많은 앱에서 활용할 수 있는 회원가입 절차 구현.
  • 내비게이션 인터페이스와 모달의 이해.
  • 여러 화면에서 공유해야하는 데이터의 관리 방법.
  • 디자인 패턴의 실제로 구현해보며 이해 증진.

새로 배우는 내용

  • Design Patterns
    • Delegation Pattern
    • Singleton
    • Target-Action
  • View Transition
    • Navigation Interface
    • Modality
  • UIKit
    • UITextField
    • UIDatePicker
    • UIStackView
    • UIImagePickerController
    • UINavigationController
    • UIGestureRecognizer
    • View Controller States Methods
  • Foundation
    • DateFormatter
  • Swift
    • Dictionary의 활용
    • guard 구문의 활용




#1. Human Interface Guidelines

H.I.G

H.I.G 문서는 앱을 개발할 때 필요한 디자인과 동작등 사용자 인터페이스를 구성하는 방법에 대한 지침 제시. 가이드라인을 따라 인터페이스를 작성하면 iOS 사용자에게 익숙한 환경 제공 가능.

학습 목표

H.I.G 문서를 왜 읽어야할지 생각해보고 내용을 전반적으로 살펴보기.

H.I.G의 내용 구성

  • Overview
  • App Architecture
  • User Interaction
  • System Capabilities
  • Visual Design
  • Icons and Images
  • Bars
  • Views
  • Controls
  • Extensions
  • Technologies
  • Resources

참고 링크

iOS Human Interface Guidelines




#2. 화면의 전환

2.1. 내비게이션 인터페이스란?

  • 계층적 구조의 화면전환을 위해 사용되는 드릴 다운 인터페이스
  • 드릴 다운 인터페이스: 선택할 수 있는 항목에 대한 세부항목이 존재하는 인터페이스
  • 내비게이션 컨트롤러를 통해 내비게이션 인터페이스 구현

내비게이션 컨트롤러

  • 컨테이너 뷰 컨트롤러로써 내비게이션 스택을 사용하여 다른 뷰 컨트롤러를 관리한다.
  • 컨텐트 뷰 컨트롤러: 내비게이션 스택에 담겨서 콘텐츠를 보여주는 뷰 컨트롤러
  • 내비게이션 컨트롤러는 두 개의 뷰를 화면에 표시.
    1. 내비게이션 스택의 최상이 뷰 컨트롤러의 콘텐츠
    2. 내비게이션 컨트롤러가 직접 관리하는 뷰 (내비게이션바 또는 툴바)
  • 내비게이션 델리게이트: 인터페이스 변화에 따른 특정 액션 동작

내비게이션 스택이란?

  • 뷰 컨트롤러를 담을 수 있는 배열과 같다.
  • 스택의 가장 밑의 뷰 컨트롤러가 루트 뷰 컨트롤러가 된다.
  • 루트 뷰 컨트롤러는 스택에서 pop 되지 않는다.
  • 스택의 가장 상위 (마지막에 push된) 뷰 컨트롤러가 화면에 보이게 된다.
  • 스택이므로 push/pop을 통해 아이템(뷰 컨트롤러)을 관리.

내비게이션 스택에서의 화면이동

  • UINavigationController 클래스의 메서드 또는 세그를 사용하여 내비게이션 스택의 뷰 컨트롤러를 추가/삭제 할 수 있다.
  • 사용자가 뒤로가기 버튼을 사용하거나 왼쪽 가장자리를 스와이프해서 이동.

내비게이션 스택의 push

스택에 새로운 뷰 컨트롤러가 푸시 될 때 UIViewController 인스턴스가 생성되고 스택에 추가된다.

  1. 초기상태: 스택에 루트 뷰 컨트롤러만 있음. (내비게이션 컨트롤러를 생성할 때 반드시 루트 뷰 컨트롤러가 설정되있어야함.)
[루트 뷰 컨트롤러]
 내비게이션 스택
  1. ‘뷰 컨트롤러1로 이동’ 버튼 눌러서 스택에 푸시
[ 뷰 컨트롤러 1  ]
[루트 뷰 컨트롤러]
 내비게이션 스택
  1. ‘뷰 컨트롤러2로 이동’ 버튼 눌러서 스택에 푸시 뷰 컨트롤러가 추가되도 하위 뷰 컨트롤러(인스턴스)가 삭제되지 않고 유지되고 있음.
[ 뷰 컨트롤러 2  ]
[ 뷰 컨트롤러 1  ]
[루트 뷰 컨트롤러]
 내비게이션 스택

내비게이션 스택의 pop

스택이 팝 될 때 생성되었던 UIViewController의 인스턴스는 다른곳에서 참조되고 있지 않다면 메모리에서 해제되고, 스택에서 삭제된다.

  1. 푸시 예제 마지막 상태에서 상단 백버튼을 눌러서 팝한다.

뷰 컨트롤러2가 스택에서 삭제된다.

       pop  ->        [ 뷰 컨트롤러 2  ]
[ 뷰 컨트롤러 1  ]
[루트 뷰 컨트롤러]
 내비게이션 스택
  1. 푸시 예제 마지막 상태에서 상단 백버튼을 눌러서 팝한다.

뷰 컨트롤러1이 스택에서 삭제된다.

       pop  ->        [ 뷰 컨트롤러 1  ]
[루트 뷰 컨트롤러]
 내비게이션 스택

UINavigationController 클래스

  • 내비게이션 컨트롤러의 생성
// 내비게이션 컨트롤러의 인스턴스를 생성하는 메서드입니다.
// 매개변수로 내비게이션 스택의 가장 아래에 있는 루트 뷰 컨트롤러가 될 뷰 컨트롤러를 넘겨줍니다.
init(rootViewController: UIViewController)
  • 내비게이션 스택의 뷰 컨트롤러에 대한 접근
// 내비게이션 스택에 있는 최상위 뷰 컨트롤러에 접근하기 위한 프로퍼티입니다.
var topViewController: UIViewController?

// 현재 내비게이션 인터페이스에서 보이는 뷰와 관련된 뷰 컨트롤러에 접근하기 위한 프로퍼티입니다.
var visibleViewController: UIViewController?

// 내비게이션 스택에 특정 뷰 컨트롤러에 접근하기 위한 프로퍼티입니다.(루트 뷰 컨트롤러의 인덱스는 0 입니다.)
var viewController: [UIViewController]
  • 내비게이션 스택의 푸시와 팝에 관한 메서드
// 내비게이션 스택에 뷰 컨트롤러를 푸시합니다.
// 푸시 된 뷰 컨트롤러는 최상위 뷰 컨트롤러로 화면에 표시됩니다.
func pushViewController(UIViewController, animated: Bool)

// 내비게이션 스택에 있는 최상위 뷰 컨트롤러를 팝합니다.
// 최상위 뷰 컨트롤러 아래에 있던 뷰 컨트롤러의 콘텐츠가 화면에 표시됩니다.
func popViewController(animated: Bool) -> UIViewController?

// 내비게이션 스택에서 루트 뷰 컨트롤러를 제외한 모든 뷰 컨트롤러를 팝합니다.
// 루트 뷰 컨트롤러가 최상위 뷰 컨트롤러가 됩니다.
// 삭제된 모든 뷰 컨트롤러의 배열이 반환됩니다.
func popToRootViewController(animated: Bool) -> [UIViewController]?

// 특정 뷰 컨트롤러가 내비게이션 스택에 최상위 뷰 컨트롤러가 되기 전까지 상위에 있는 뷰 컨트롤러들을 팝합니다.
func popToViewController(_ viewController: UIViewController, 
		animated: Bool) -> [UIViewController]?

내비게이션 인터페이스를 구성하는 두 가지 방법

스토리보드를 사용하여 구성하기

  1. 스토리보드에서 뷰 컨트롤러 선택
  2. 메뉴 [Editor] - [Embed In] - [Navigation Controller] 선택
  3. 선택한 뷰 컨트롤러가 루트 뷰 컨트롤러가 되면서 내비게이션 컨트롤러 생성됨
  4. 위 방법 외에도 객체 라이브러리에서 내비게이션 컨트롤러를 드래그 앤 드롭해서 만들 수 있다.

코드작성을 통해 내비게이션 인터페이스 구성하기

코드로 생성하면 내비게이션 컨트롤러가 생성되기 원하는 지점에 생성할 수 있다. 예를 들어 내비게이션 컨트롤러가 애플리케이션 윈도우의 루트 뷰 역할을 한다면, ‘applicationDidFinishLaunching:’메서드에 구현할 수 있다.

  1. 루트 뷰 컨트롤러가 될 뷰 컨트롤러 생성.
  2. init(rootViewController: UIViewController) 메서드를 통해 내비게이션 컨트롤러를 초기화하고 생성.
  3. 내비게이션 컨트롤러를 윈도우의 루트 뷰 컨트롤러로 설정.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        // 루트 뷰 컨트롤러가 될 뷰 컨트롤러를 생성합니다.
        let rootViewController = UIViewController()
        // 위에서 생성한 뷰 컨트롤러로 내비게이션 컨트롤러를 생성합니다.
        let navigationController = UINavigationController(rootViewController: rootViewController)
        
        self.window = UIWindow(frame: UIScreen.main.bounds)
        // 윈도우의 루트 뷰 컨트롤러로 내비게이션 컨트롤러를 설정합니다.
        self.window?.rootViewController = navigationController
        self.window?.makeKeyAndVisible()
        
        return true
    }

내비게이션바의 구성

  • 내비게이션 바는 내비게이션 컨트롤러에 의해 생성됨
  • 컨트롤러의 관리를 받는 모든 뷰 컨트롤러의 상단에 표시되며 최상위 뷰 컨트롤러가 변경될 때마다 업데이트 함

참고 문서/링크

2.2. 내비게이션 인터페이스 구현해보기

  1. 프로젝트 생성 - ViewTransition
  2. 뷰 컨트롤러 추가
    1. 스토리 보드에 뷰 컨트롤러 추가
    2. SecondViewController 파일 생성
    3. 스토리 보드의 뷰 컨트롤러와 연결
  3. 내비게이션 컨트롤러 추가
    • 기본 뷰 컨트롤러 선택 후 메뉴 [Editor] - [Embed In] - [Navigation Controller] 선택
  4. push (세그로 연결)
    1. 기본 뷰 컨트롤러에 “PUSH” 버튼 추가
    2. Second 뷰 컨트롤러로 세그 연결 (컨트롤+드래그, Show)
  5. pop (코드로 연결)
    1. Second 뷰 컨트롤러에 “POP”버튼 추가
    2. popToPrev() 함수만들고 “.popViewController()”함수 추가
    3. 스토리보드에서 액션과 버튼 연결

2.3. 모달이란?

  • 모달(Modal): 사용자의 이목을 끌기위해 사용하는 화면전환 기법.
  • 이목을 집중해야 하는 화면을 다른 화면 위로 띄워(Presenting) 표현하는 방식.
  • 모달로 보이는 화면을 사라지게 하려면 반드시 ‘확인’, ‘취소’등 특정 선택을 해야 함.
  • 이목을 끌어야 하는 화면에 사용하며 되도록 단순하고 사용자가 빠르게 처리할 수 이는 내용이 좋다.

Presenting a View Controller

  • UIViewController 클래스에 나타내기(present) 기능 내장되어 모든 뷰 컨트롤러 객체에서 사용가능.
  • 뷰 컨트롤러를 나타내면 원래 뷰 컨트롤러(presenting view controller)와 새롭게 나타나는 뷰 컨트롤러(presented view controller) 간의 관계가 생성되며, 나타나는 뷰 컨트롤러가 사라질(dimissed) 때까지 유지된다.

프레젠테이션 및 전환 프로세스

  • 뷰 컨트롤러의 프레젠 테이션은 새로운 콘텐츠를 화면에 애니메이션으로 표시할 수 있는 쉽고 빠른 방법.
  • 내장 프레젠 테이션과 애니메이션은 ‘UIKit’이 모두 처리하기에 아주 적은 코드로 가능하고 커스텀도 가능.
  • 프로그래밍 또는 세그 사용해서 구현.

프레젠테이션 스타일

뷰 컨트롤러가 화면에 나타나는 모양.

  • 전체화면 프레젠테이션 스타일
    • 화면 전체를 덮으며 아래의 콘텐츠와 상호작용 방지.
    • 일반적으로, UIKitUIModalPresentationFullScreen 스타일을 사용하여 아래에 위치한 뷰는 화면에서 보이지 않는다. 대신, UIModalPresentationOverFullScreen 스타일을 지정하여 아래의 뷰가 완전히 보이지 않는 것을 막을 수 있다.
  • 팝오버 스타일
    • 추가 정보, 선택한 객체와 관련된 목록 표시에 유용하다.
    • 합업 뷰 외부에 탭하면 자동으로 dimiss 된다.
    • iPad에서만 지원.
  • 현재 컨텍스트 스타일
    • 아래 뷰 컨트롤러의 콘텐츠 영역에 콘텐츠를 올리는 형태.
  • 커스텀 프레젠테이션 스타일
  • 전환 스타일 (Transition Styles)
    • 뷰 컨트롤러를 표시하는데 사용하는 애니메이션의 유형

뷰 컨트롤러를 나타내기 VS 보여주기 (Presenting VS Showing a View Controller)

  • 뷰 컨트롤러 표시하기 (Presenting a View Controller)
  • 뷰 컨트롤러 보여주기 (Showing View Controller)
    1. 나타나는 뷰 컨트롤러 객체 만들기. 데이터 초기화는 직접 해야함
    2. 프레젠테이션 스타일 설정
    3. 전환 애니메이션 설정
    4. 현재 뷰 컨트롤러의 ‘showViewController:sender:’, ‘showDetailViewController:sender:’ 메소드 호출
  • 뷰 컨트롤러를 모달로 표시하기 (Presenting View Controllers modally)
  • 팝오버에 뷰 컨트롤러 나타내기 (Presenting a View Controller in a Popover)
  • 나타난 뷰 컨트롤러 닫기 (Dismissing a Presented View Controller)
    • 뷰 컨트롤러의 dismiss(animated:completion:) 메서드 호출하면 자동으로 이 요청을 나타내는 뷰 컨트롤러로 전달함.
  • 다른 스토리보드에서 정의된 뷰 컨트롤러 나타내기
    • 하나의 스토리보드에 있는 뷰 컨트롤러 사이에서는 세그를 생성 할 수 있지만, 스토리보드 간의 세그는 생성 불가.
    • 다른 스토리보드의 뷰 컨트롤러를 나타내려면 먼저 인스턴스화 해야한다.
    • 모달 또는 푸시 등으로 나타낼 수 있다. ~~~swift 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) } ~~~

  • 스토리보드가 여러 개 일때 유용할 수 있는 사례
    1. 대규모 프로그래밍팀에서 사용자 인터페이스의 서로 다른 부분이 각각 할당 된 경우, 충돌을 최소화 하기위해 서로 다른 스토리보드를 만든다.
    2. 뷰 컨트롤러 유형 컬렉션을 사전 정의하는 라이브러리를 사용하거나 생성하는 경우 라이브러리에서 제공하는 스토리보드가 있다.
    3. 외부 화면에서 나타내야 하는 콘텐츠의 경우, 연관된 모든 뷰 컨트롤러를 서로 다른 스토리보드에 보관해야한다.

참고 링크

2.4. 모달 구현해보기

  1. 이전 프로젝트에서 이어짐 - ViewTransition
  2. 새 뷰컨트롤러를 두 개 생성하고 ViewController, SecondViewController로 연결하기.
  3. 새 ViewController를 initial 로 설정
  4. Present Modal 버튼 생성하고 Second 뷰 컨트롤러로 액션 세그 “Present Modally” 연결
  5. Dismiss Modall 버튼을 Second 뷰 컨트롤러에 생성하고 액션 메소드 dismissModa() 만들고 버튼과 dismissModal로 연결

용도에 따른 사용

  • 내비게이션 인터페이스
    • 정보의 흐름이 연결될 때 (설정 앱)
  • 모달
    • 단순한 팝업
    • 입력 폼 (메시지 앱의 Info버튼)

Leave a comment