부스트코스 “iOS 프로그래밍” 요약정리 - 2. 회원가입 화면 구현 #0 ~ #2
- Ref: 부스트코스 - iOS 프로그래밍
#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. 내비게이션 인터페이스란?
- 계층적 구조의 화면전환을 위해 사용되는 드릴 다운 인터페이스
- 드릴 다운 인터페이스: 선택할 수 있는 항목에 대한 세부항목이 존재하는 인터페이스
- 내비게이션 컨트롤러를 통해 내비게이션 인터페이스 구현
내비게이션 컨트롤러
- 컨테이너 뷰 컨트롤러로써 내비게이션 스택을 사용하여 다른 뷰 컨트롤러를 관리한다.
- 컨텐트 뷰 컨트롤러: 내비게이션 스택에 담겨서 콘텐츠를 보여주는 뷰 컨트롤러
- 내비게이션 컨트롤러는 두 개의 뷰를 화면에 표시.
- 내비게이션 스택의 최상이 뷰 컨트롤러의 콘텐츠
- 내비게이션 컨트롤러가 직접 관리하는 뷰 (내비게이션바 또는 툴바)
- 내비게이션 델리게이트: 인터페이스 변화에 따른 특정 액션 동작
내비게이션 스택이란?
- 뷰 컨트롤러를 담을 수 있는 배열과 같다.
- 스택의 가장 밑의 뷰 컨트롤러가 루트 뷰 컨트롤러가 된다.
- 루트 뷰 컨트롤러는 스택에서 pop 되지 않는다.
- 스택의 가장 상위 (마지막에 push된) 뷰 컨트롤러가 화면에 보이게 된다.
- 스택이므로 push/pop을 통해 아이템(뷰 컨트롤러)을 관리.
내비게이션 스택에서의 화면이동
- UINavigationController 클래스의 메서드 또는 세그를 사용하여 내비게이션 스택의 뷰 컨트롤러를 추가/삭제 할 수 있다.
- 사용자가 뒤로가기 버튼을 사용하거나 왼쪽 가장자리를 스와이프해서 이동.
내비게이션 스택의 push
스택에 새로운 뷰 컨트롤러가 푸시 될 때 UIViewController 인스턴스가 생성되고 스택에 추가된다.
- 초기상태: 스택에 루트 뷰 컨트롤러만 있음. (내비게이션 컨트롤러를 생성할 때 반드시 루트 뷰 컨트롤러가 설정되있어야함.)
[루트 뷰 컨트롤러]
내비게이션 스택
- ‘뷰 컨트롤러1로 이동’ 버튼 눌러서 스택에 푸시
[ 뷰 컨트롤러 1 ]
[루트 뷰 컨트롤러]
내비게이션 스택
- ‘뷰 컨트롤러2로 이동’ 버튼 눌러서 스택에 푸시 뷰 컨트롤러가 추가되도 하위 뷰 컨트롤러(인스턴스)가 삭제되지 않고 유지되고 있음.
[ 뷰 컨트롤러 2 ]
[ 뷰 컨트롤러 1 ]
[루트 뷰 컨트롤러]
내비게이션 스택
내비게이션 스택의 pop
스택이 팝 될 때 생성되었던 UIViewController의 인스턴스는 다른곳에서 참조되고 있지 않다면 메모리에서 해제되고, 스택에서 삭제된다.
- 푸시 예제 마지막 상태에서 상단 백버튼을 눌러서 팝한다.
뷰 컨트롤러2가 스택에서 삭제된다.
pop -> [ 뷰 컨트롤러 2 ]
[ 뷰 컨트롤러 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]?
내비게이션 인터페이스를 구성하는 두 가지 방법
스토리보드를 사용하여 구성하기
- 스토리보드에서 뷰 컨트롤러 선택
- 메뉴 [Editor] - [Embed In] - [Navigation Controller] 선택
- 선택한 뷰 컨트롤러가 루트 뷰 컨트롤러가 되면서 내비게이션 컨트롤러 생성됨
- 위 방법 외에도 객체 라이브러리에서 내비게이션 컨트롤러를 드래그 앤 드롭해서 만들 수 있다.
코드작성을 통해 내비게이션 인터페이스 구성하기
코드로 생성하면 내비게이션 컨트롤러가 생성되기 원하는 지점에 생성할 수 있다. 예를 들어 내비게이션 컨트롤러가 애플리케이션 윈도우의 루트 뷰 역할을 한다면, ‘applicationDidFinishLaunching:’메서드에 구현할 수 있다.
- 루트 뷰 컨트롤러가 될 뷰 컨트롤러 생성.
init(rootViewController: UIViewController)
메서드를 통해 내비게이션 컨트롤러를 초기화하고 생성.- 내비게이션 컨트롤러를 윈도우의 루트 뷰 컨트롤러로 설정.
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
}
내비게이션바의 구성
- 내비게이션 바는 내비게이션 컨트롤러에 의해 생성됨
- 컨트롤러의 관리를 받는 모든 뷰 컨트롤러의 상단에 표시되며 최상위 뷰 컨트롤러가 변경될 때마다 업데이트 함
참고 문서/링크
- View Controller Catalog for iOS - 1 [Navigation Controllers]
- PDF의 문서읽기 순서에 따라 꼭 읽고 이해하자.
-
Navigation - App Architecture - iOS Human Interface Guidelines
- UINavigationController - UIKit - Apple Developer Documentation
2.2. 내비게이션 인터페이스 구현해보기
- 프로젝트 생성 - ViewTransition
- 뷰 컨트롤러 추가
- 스토리 보드에 뷰 컨트롤러 추가
- SecondViewController 파일 생성
- 스토리 보드의 뷰 컨트롤러와 연결
- 내비게이션 컨트롤러 추가
- 기본 뷰 컨트롤러 선택 후 메뉴 [Editor] - [Embed In] - [Navigation Controller] 선택
- push (세그로 연결)
- 기본 뷰 컨트롤러에 “PUSH” 버튼 추가
- Second 뷰 컨트롤러로 세그 연결 (컨트롤+드래그, Show)
- pop (코드로 연결)
- Second 뷰 컨트롤러에 “POP”버튼 추가
- popToPrev() 함수만들고 “.popViewController()”함수 추가
- 스토리보드에서 액션과 버튼 연결
2.3. 모달이란?
- 모달(Modal): 사용자의 이목을 끌기위해 사용하는 화면전환 기법.
- 이목을 집중해야 하는 화면을 다른 화면 위로 띄워(Presenting) 표현하는 방식.
- 모달로 보이는 화면을 사라지게 하려면 반드시 ‘확인’, ‘취소’등 특정 선택을 해야 함.
- 이목을 끌어야 하는 화면에 사용하며 되도록 단순하고 사용자가 빠르게 처리할 수 이는 내용이 좋다.
Presenting a View Controller
- UIViewController 클래스에 나타내기(present) 기능 내장되어 모든 뷰 컨트롤러 객체에서 사용가능.
- 뷰 컨트롤러를 나타내면 원래 뷰 컨트롤러(presenting view controller)와 새롭게 나타나는 뷰 컨트롤러(presented view controller) 간의 관계가 생성되며, 나타나는 뷰 컨트롤러가 사라질(dimissed) 때까지 유지된다.
프레젠테이션 및 전환 프로세스
- 뷰 컨트롤러의 프레젠 테이션은 새로운 콘텐츠를 화면에 애니메이션으로 표시할 수 있는 쉽고 빠른 방법.
- 내장 프레젠 테이션과 애니메이션은 ‘UIKit’이 모두 처리하기에 아주 적은 코드로 가능하고 커스텀도 가능.
- 프로그래밍 또는 세그 사용해서 구현.
프레젠테이션 스타일
뷰 컨트롤러가 화면에 나타나는 모양.
- 전체화면 프레젠테이션 스타일
- 화면 전체를 덮으며 아래의 콘텐츠와 상호작용 방지.
- 일반적으로,
UIKit
은UIModalPresentationFullScreen
스타일을 사용하여 아래에 위치한 뷰는 화면에서 보이지 않는다. 대신,UIModalPresentationOverFullScreen
스타일을 지정하여 아래의 뷰가 완전히 보이지 않는 것을 막을 수 있다.
- 팝오버 스타일
- 추가 정보, 선택한 객체와 관련된 목록 표시에 유용하다.
- 합업 뷰 외부에 탭하면 자동으로 dimiss 된다.
- iPad에서만 지원.
- 현재 컨텍스트 스타일
- 아래 뷰 컨트롤러의 콘텐츠 영역에 콘텐츠를 올리는 형태.
- 커스텀 프레젠테이션 스타일
- 전환 스타일 (Transition Styles)
- 뷰 컨트롤러를 표시하는데 사용하는 애니메이션의 유형
뷰 컨트롤러를 나타내기 VS 보여주기 (Presenting VS Showing a View Controller)
- 뷰 컨트롤러 표시하기 (Presenting a View Controller)
- 자동으로 표시하려면 세그 사용 참고: 세그 사용하기
- 뷰 컨트롤러 보여주기 (Showing View Controller)
- 나타나는 뷰 컨트롤러 객체 만들기. 데이터 초기화는 직접 해야함
- 프레젠테이션 스타일 설정
- 전환 애니메이션 설정
- 현재 뷰 컨트롤러의 ‘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) } ~~~
- 스토리보드가 여러 개 일때 유용할 수 있는 사례
- 대규모 프로그래밍팀에서 사용자 인터페이스의 서로 다른 부분이 각각 할당 된 경우, 충돌을 최소화 하기위해 서로 다른 스토리보드를 만든다.
- 뷰 컨트롤러 유형 컬렉션을 사전 정의하는 라이브러리를 사용하거나 생성하는 경우 라이브러리에서 제공하는 스토리보드가 있다.
- 외부 화면에서 나타내야 하는 콘텐츠의 경우, 연관된 모든 뷰 컨트롤러를 서로 다른 스토리보드에 보관해야한다.
참고 링크
2.4. 모달 구현해보기
- 이전 프로젝트에서 이어짐 - ViewTransition
- 새 뷰컨트롤러를 두 개 생성하고 ViewController, SecondViewController로 연결하기.
- 새 ViewController를 initial 로 설정
- Present Modal 버튼 생성하고 Second 뷰 컨트롤러로 액션 세그 “Present Modally” 연결
- Dismiss Modall 버튼을 Second 뷰 컨트롤러에 생성하고 액션 메소드 dismissModa() 만들고 버튼과 dismissModal로 연결
용도에 따른 사용
- 내비게이션 인터페이스
- 정보의 흐름이 연결될 때 (설정 앱)
- 모달
- 단순한 팝업
- 입력 폼 (메시지 앱의 Info버튼)
Leave a comment