[UMC] 스터디 3주차 : 생명주기 화면전환
IOS 3주차 워크북(생명주기와 화면 전환: 값 전달)
📝 학습 목표
- Life Cycle에 대해 이해하고 활용할 수 있다.
- Optional에 대해 이해하고 Optional Unwrapping을 활용할 수 있다.
- 화면 전환에 대해 이해하고 상황에 맞는 방법을 사용할 수 있다.
- 데이터 전달하는 방법을 이해하고 상황에 맞는 방법을 사용할 수 있다.
✍🏻 수업 내용 정리
- 세미나를 들으며 들으며 느낀 점, 배운 점들을 정리해보세요! -
🎞 미션 검사 및 피드백
(멘토님) 위에서 → 아래로 보통 레이아웃 짜기
컴포넌트들에 대해 설계를 미리 진행한 분-계층별로-도 계심(인상 깊음)
만약 동일한 ui 반복될 때, 활용할 수 있는 요소 : tableView, collectionView (다음 세미나)
이미지 asset 활용 시, 이미지 크기 조절→이미지 넣기 전에 수정하거나 ,ui image resize 키워드 검색해보기
레이아웃끼리 충돌할 때(그래서 큰 화면 작은 화면 다름): less than or equal 또는 Greater than equal 활용
🕹 화면 전환
저번 챌린지 미션에서 공부한 내용
- view Controller의 View 위에 다른 View를 가져와 바꿔치기
- View Controller에서 다른 View Controller를 호출하여 전환하기
- Navigation Controller를 사용하여 화면 전환하기
- 화면 전환용 객체 세그웨이를 사용하여 화면 전환하기
🎛 라이프 사이클
View에게 생명주기는 무슨 의미일까?
화면은 보여졌다가 사라지는 즉 탄생하고 소멸하기까지 한 사이클을 말한다.
총 8 단계로 전부 외울 필요 없음
애플에서 세분화시킨 라이프사이클
init: 신생아가 태어나는 순간(뷰가 탄생하는 순간)
loadView: 태어나서 태어났다고 들을 때
viewDidLoad: (중요) 이 8가지 각각 단계는 스윽 봐도
이 viewDidLoad는 뷰 계층이 최초 메모리에 로드된 후 호출되는 메서드 메모리에 처음 로딩 될 때 1회만 호출됨
애기가 태어나서 출생 신고를 할 때
-라이프사이클의 탄생 배경: 모바일에서는 화면 별 역할이 구성되어있어서(단계를 나누어 화면을 쪼개서 진행해서) ↔ 데스크탑과는 다르다!
그래서 뷰의 전환이 잦게 되어, 생명주기를 다루게 됨
😇 생명주기
😩내가 헷갈렸던 거
SceneDelegate에 있는 화면 전환 관련 함수들
SceneWillEnterForeground
sceneDidBecomeActive (앱 실행하면 여기까지)
scenewillResignActive. (앱이 곧 비활성화 될거야)
sceneDidDisconnect (앱이 꺼지는 순간에)
sceneDidEnterBackground (앱이 백그라운드 상태에 진입)
🎯 핵심 키워드
- ViewController Life Cycle
-
loadView
You should never call this method directly. The view controller calls this method when its
[view](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621460-view)
property is requested but is currentlynil
. This method loads or creates a view and assigns it to the[view](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621460-view)
property.If the view controller has an associated nib file, this method loads the view from the nib file. A view controller has an associated nib file if the
[nibName](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621487-nibname)
property returns a non-nil
value, which occurs if the view controller was instantiated from a storyboard, if you explicitly assigned it a nib file using the[init(nibName:bundle:)](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621359-init)
method, or if iOS finds a nib file in the app bundle with a name based on the view controller’s class name. If the view controller does not have an associated nib file, this method creates a plain[UIView](https://developer.apple.com/documentation/uikit/uiview)
object instead.If you use Interface Builder to create your views and initialize the view controller, you must not override this method.
You can override this method in order to create your views manually. If you choose to do so, assign the root view of your view hierarchy to the
[view](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621460-view)
property. The views you create should be unique instances and should not be shared with any other view controller object. Your custom implementation of this method should not callsuper
.If you want to perform any additional initialization of your views, do so in the
[viewDidLoad()](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621495-viewdidload)
method. -
viewDidLoad
You can override this method to perform tasks to immediately follow the setting of the
[view](https://developer.apple.com/documentation/appkit/nsviewcontroller/1434401-view)
property.Typically, your override would perform one-time instantiation and initialization of the contents of the view controller’s view. If you override this method, call this method on
super
at some point in your implementation in case a superclass also overrides this method.For a view controller originating in a nib file, this method is called immediately after the
[view](https://developer.apple.com/documentation/appkit/nsviewcontroller/1434401-view)
property is set. For a view controller created programmatically, this method is called immediately after the[loadView()](https://developer.apple.com/documentation/appkit/nsviewcontroller/1434405-loadview)
method completes.The default implementation of this method does nothing.
-
viewWillAppear
This method is called before the view controller’s view is about to be added to a view hierarchy and before any animations are configured for showing the view. You can override this method to perform custom tasks associated with displaying the view. For example, you might use this method to change the orientation or style of the status bar to coordinate with the orientation or style of the view being presented. If you override this method, you must call
super
at some point in your implementation.For more information about the how views are added to view hierarchies by a view controller, and the sequence of messages that occur, see Supporting Accessibility.
-
viewDidAppear
You can override this method to perform additional tasks associated with presenting the view. If you override this method, you must call
super
at some point in your implementation. -
viewWillDisappear
This method is called in response to a view being removed from a view hierarchy. This method is called before the view is actually removed and before any animations are configured.
Subclasses can override this method and use it to commit editing changes, resign the first responder status of the view, or perform other relevant tasks. For example, you might use this method to revert changes to the orientation or style of the status bar that were made in the
[viewDidAppear(_:)](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621423-viewdidappear)
method when the view was first presented. If you override this method, you must callsuper
at some point in your implementation. -
viewDidDisappear
You can override this method to perform additional tasks associated with dismissing or hiding the view. If you override this method, you must call
super
at some point in your implementation.
-
-
Optional
## Declaration
@frozen enum Optional<Wrapped>
## Overview
You use the
Optional
type whenever you use optional values, even if you never type the wordOptional
. Swift’s type system usually shows the wrapped type’s name with a trailing question mark (?
) instead of showing the full type name. For example, if a variable has the typeInt?
, that’s just another way of writingOptional<Int>
. The shortened form is preferred for ease of reading and writing code.The types of
shortForm
andlongForm
in the following code sample are the same:let shortForm: Int? = Int("42")let longForm: Optional<Int> = Int("42")
The
Optional
type is an enumeration with two cases.Optional.none
is equivalent to thenil
literal.Optional.some(Wrapped)
stores a wrapped value. For example:let number: Int? = Optional.some(42)let noNumber: Int? = Optional.noneprint(noNumber == nil)// Prints "true"
You must unwrap the value of an
Optional
instance before you can use it in many contexts. Because Swift provides several ways to safely unwrap optional values, you can choose the one that helps you write clear, concise code.The following examples use this dictionary of image names and file paths:
let imagePaths = ["star": "/glyphs/star.png", "portrait": "/images/content/portrait.jpg", "spacer": "/images/shared/spacer.gif"]
Getting a dictionary’s value using a key returns an optional value, so
imagePaths["star"]
has typeOptional<String>
or, written in the preferred manner,String?
.## Optional Binding
To conditionally bind the wrapped value of an
Optional
instance to a new variable, use one of the optional binding control structures, includingif let
,guard let
, andswitch
.if let starPath = imagePaths["star"] { print("The star image is at '\(starPath)'")} else { print("Couldn't find the star image")}// Prints "The star image is at '/glyphs/star.png'"
## Optional Chaining
To safely access the properties and methods of a wrapped instance, use the postfix optional chaining operator (postfix
?
). The following example uses optional chaining to access thehasSuffix(_:)
method on aString?
instance.if imagePaths["star"]?.hasSuffix(".png") == true { print("The star image is in PNG format")}// Prints "The star image is in PNG format"
## Using the Nil-Coalescing Operator
Use the nil-coalescing operator (
??
) to supply a default value in case theOptional
instance isnil
. Here a default path is supplied for an image that is missing fromimagePaths
.let defaultImagePath = "/images/default.png"let heartPath = imagePaths["heart"] ?? defaultImagePathprint(heartPath)// Prints "/images/default.png"
The
??
operator also works with anotherOptional
instance on the right-hand side. As a result, you can chain multiple??
operators together.let shapePath = imagePaths["cir"] ?? imagePaths["squ"] ?? defaultImagePathprint(shapePath)// Prints "/images/default.png"
## Unconditional Unwrapping
When you’re certain that an instance of
Optional
contains a value, you can unconditionally unwrap the value by using the forced unwrap operator (postfix!
). For example, the result of the failableInt
initializer is unconditionally unwrapped in the example below.let number = Int("42")!print(number)// Prints "42"
You can also perform unconditional optional chaining by using the postfix
!
operator.let isPNG = imagePaths["star"]!.hasSuffix(".png")print(isPNG)// Prints "true"
Unconditionally unwrapping a
nil
instance with!
triggers a runtime error. -
Optional Binding
## Optional Binding
To conditionally bind the wrapped value of an
Optional
instance to a new variable, use one of the optional binding control structures, includingif let
,guard let
, andswitch
.if let starPath = imagePaths["star"] { print("The star image is at '\(starPath)'")} else { print("Couldn't find the star image")}// Prints "The star image is at '/glyphs/star.png'"
-
Optional Chaining
## Optional Chaining
To safely access the properties and methods of a wrapped instance, use the postfix optional chaining operator (postfix
?
). The following example uses optional chaining to access thehasSuffix(_:)
method on aString?
instance.if imagePaths["star"]?.hasSuffix(".png") == true { print("The star image is in PNG format")}// Prints "The star image is in PNG format"
-
Forced Unwrapping
강제로 옵셔널 벗겨내기 → ! 사용
-
guard문
guard let (옵셔널 바인딩일 때)
- 옵셔널을 벗겼을 때 nil이면 더 이상 코드를 실행시키지 않겠다는 의미가 강함 -> nil이 아닐 때만 관심을 갖겠다.
- 선언된 변수를 아래문장에서 사용 가능 (동일한 스코프로 취급)
guard 조건 else { // 조건이 false 이면 else 구문이 실행되고return or throw or break 를 통해 이 후 코드를 실행하지 않도록 한다. }
간단하게 설명하자면 아래와 같이 말 할 수 있을 것입니다!
- 뭔가를 검사하여 그 다음에 오는 코드를 실행할지 말지 결정 하는 것
- guard 문에 주어진 조건문이 거짓일 때 구문이 실행됨
- 화면 전환
-
present
## Declaration
func present( _ viewControllerToPresent: [UIViewController](https://developer.apple.com/documentation/uikit/uiviewcontroller), animated flag: [Bool](https://developer.apple.com/documentation/swift/bool), completion: (() -> [Void](https://developer.apple.com/documentation/swift/void))? = nil )
**Parameters**
viewControllerToPresent
The view controller to display over the current view controller’s content.flag
Passtrue
to animate the presentation; otherwise, passfalse
.completion
The block to execute after the presentation finishes. This block has no return value and takes no parameters. You may specifynil
for this parameter. -
Navigation Controller
## Declaration
@MainActor class UINavigationController : UIViewController
## Overview
A navigation controller is a container view controller that manages one or more child view controllers in a navigation interface. In this type of interface, only one child view controller is visible at a time. Selecting an item in the view controller pushes a new view controller onscreen using an animation, hiding the previous view controller. Tapping the back button in the navigation bar at the top of the interface removes the top view controller, thereby revealing the view controller underneath.
Use a navigation interface to mimic the organization of hierarchical data managed by your app. At each level of the hierarchy, you provide an appropriate screen (managed by a custom view controller) to display the content at that level. The following image shows an example of the navigation interface presented by the Settings application in iOS Simulator. The first screen presents the user with the list of applications that contain preferences. Selecting an application reveals individual settings and groups of settings for that application. Selecting a group yields more settings and so on. For all but the root view, the navigation controller provides a back button to allow the user to move back up the hierarchy.
A navigation controller object manages its child view controllers using an ordered array, known as the navigation stack. The first view controller in the array is the root view controller and represents the bottom of the stack. The last view controller in the array is the topmost item on the stack, and represents the view controller currently being displayed. You add and remove view controllers from the stack using segues or using the methods of this class. The user can also remove the topmost view controller using the back button in the navigation bar or using a left-edge swipe gesture.
The navigation controller manages the navigation bar at the top of the interface and an optional toolbar at the bottom of the interface. The navigation bar is always present and is managed by the navigation controller itself, which updates the navigation bar using the content provided by its child view controllers. When the
[isToolbarHidden](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621875-istoolbarhidden)
property isfalse
, the navigation controller similarly updates the toolbar with contents provided by the topmost view controller.A navigation controller coordinates its behavior with its
[delegate](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621876-delegate)
object. The delegate object can override the pushing or popping of view controllers, provide custom animation transitions, and specify the preferred orientation for the navigation interface. The delegate object you provide must conform to the[UINavigationControllerDelegate](https://developer.apple.com/documentation/uikit/uinavigationcontrollerdelegate)
protocol.The following image shows the relationships between the navigation controller and the objects it manages. Use the specified properties of the navigation controller to access these objects.
### Navigation controller views
A navigation controller is a container view controller — that is, it embeds the content of other view controllers inside of itself. You access a navigation controller’s view from its
[view](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621460-view)
property. This view incorporates the navigation bar, an optional toolbar, and the content view corresponding to the topmost view controller. The following image shows how these views are assembled to present the overall navigation interface. (In this figure, the navigation interface is further embedded inside a tab bar interface.) Although the content of the navigation bar and toolbar views changes, the views themselves don’t. The only view that actually changes is the custom content view provided by the topmost view controller on the navigation stack.Note Because the content view underlaps the navigation bar in iOS 7 and later, you must consider that space when designing your view controller content.
The navigation controller manages the creation, configuration, and display of the navigation bar and optional navigation toolbar. It’s permissible to customize the navigation bar’s appearance-related properties but you must never change its
[frame](https://developer.apple.com/documentation/uikit/uiview/1622621-frame)
,[bounds](https://developer.apple.com/documentation/uikit/uiview/1622580-bounds)
, or[alpha](https://developer.apple.com/documentation/uikit/uiview/1622417-alpha)
values directly. If you subclassUINavigationBar
, you must initialize your navigation controller using the[init(navigationBarClass:toolbarClass:)](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621866-init)
method. To hide or show the navigation bar, use the[isNavigationBarHidden](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621850-isnavigationbarhidden)
property or[setNavigationBarHidden(_:animated:)](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621885-setnavigationbarhidden)
method.A navigation controller builds the contents of the navigation bar dynamically using the navigation item objects (instances of the
[UINavigationItem](https://developer.apple.com/documentation/uikit/uinavigationitem)
class) associated with the view controllers on the navigation stack. To customize the overall appearance of a navigation bar, use[UIAppearance](https://developer.apple.com/documentation/uikit/uiappearance)
APIs. To change the contents of the navigation bar, you must therefore configure the navigation items of your custom view controllers. For more information about navigation items, see[UINavigationItem](https://developer.apple.com/documentation/uikit/uinavigationitem)
.### Updating the navigation bar
Each time the top-level view controller changes, the navigation controller updates the navigation bar accordingly. Specifically, the navigation controller updates the bar button items displayed in each of the three navigation bar positions: left, middle, and right. Bar button items are instances of the
[UIBarButtonItem](https://developer.apple.com/documentation/uikit/uibarbuttonitem)
class. You can create items with custom content or create standard system items depending on your needs.Tinting of the navigation bar is controlled by properties of the navigation bar itself. Use the
[tintColor](https://developer.apple.com/documentation/uikit/uinavigationbar/1624937-tintcolor)
property to change the tint color of items in the bar and use the[barTintColor](https://developer.apple.com/documentation/uikit/uinavigationbar/1624931-bartintcolor)
property to change the tint color of the bar itself. Navigation bars don’t inherit their tint color from the currently displayed view controller.For more information about the navigation bar, see
[UINavigationBar](https://developer.apple.com/documentation/uikit/uinavigationbar)
. For more information about how to create bar button items, see[UIBarButtonItem](https://developer.apple.com/documentation/uikit/uibarbuttonitem)
.### The left item
For all but the root view controller on the navigation stack, the item on the left side of the navigation bar provides navigation back to the previous view controller. The contents of this left-most button are determined as follows:
- If the new top-level view controller has a custom left bar button item, that item is displayed. To specify a custom left bar button item, set the
[leftBarButtonItem](https://developer.apple.com/documentation/uikit/uinavigationitem/1624936-leftbarbuttonitem)
property of the view controller’s navigation item. - If the top-level view controller doesn’t have a custom left bar button item, but the navigation item of the previous view controller has an object in its
[backBarButtonItem](https://developer.apple.com/documentation/uikit/uinavigationitem/1624958-backbarbuttonitem)
property, the navigation bar displays that item. - If a custom bar button item isn’t specified by either of the view controllers, a default back button is used and its title is set to the value of the
[title](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621364-title)
property of the previous view controller — that is, the view controller one level down on the stack. (If there’s only one view controller on the navigation stack, no back button is displayed.)
Note In cases where the title of a back button is too long to fit in the available space, the navigation bar may substitute the string “Back” for the actual button title. The navigation bar does this only if the back button is provided by the previous view controller. If the new top-level view controller has a custom left bar button item — an object in the
[leftBarButtonItem](https://developer.apple.com/documentation/uikit/uinavigationitem/1624936-leftbarbuttonitem)
or[leftBarButtonItems](https://developer.apple.com/documentation/uikit/uinavigationitem/1624946-leftbarbuttonitems)
property of its navigation item—the navigation bar doesn’t change the button title.### The middle item
The navigation controller updates the middle of the navigation bar as follows:
- If the new top-level view controller has a custom title view, the navigation bar displays that view in place of the default title view. To specify a custom title view, set the
[titleView](https://developer.apple.com/documentation/uikit/uinavigationitem/1624935-titleview)
property of the view controller’s navigation item. - If no custom title view is set, the navigation bar displays a label containing the view controller’s default title. The string for this label is usually obtained from the
[title](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621364-title)
property of the view controller itself. If you want to display a different title than the one associated with the view controller, set thetitle
property of the view controller’s navigation item instead.
### The right item
The navigation controller updates the right side of the navigation bar as follows:
- If the new top-level view controller has a custom right bar button item, that item is displayed. To specify a custom right bar button item, set the
[rightBarButtonItem](https://developer.apple.com/documentation/uikit/uinavigationitem/1624957-rightbarbuttonitem)
property of the view controller’s navigation item. - If no custom right bar button item is specified, the navigation bar displays nothing on the right side of the bar.
### Displaying a toolbar
A navigation controller object manages an optional toolbar in its view hierarchy. When displayed, this toolbar obtains its current set of items from the
[toolbarItems](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621867-toolbaritems)
property of the active view controller. When the active view controller changes, the navigation controller updates the toolbar items to match the new view controller, animating the new items into position when appropriate.The navigation toolbar is hidden by default but you can show it for your navigation interface by calling the
[setToolbarHidden(_:animated:)](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621888-settoolbarhidden)
method of your navigation controller object. If not all of your view controllers support toolbar items, your delegate object can call this method to toggle the visibility of the toolbar during subsequent push and pop operations. To use a customUIToolbar
subclass, initialize the navigation controller using the[init(navigationBarClass:toolbarClass:)](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621866-init)
method. If you use custom toolbar and navigation bar subclasses to create a navigation controller, note that you’re responsible for pushing and setting view controllers before presenting the navigation controller onscreen.### Adapting to different environments
The navigation interface remains the same in both horizontally compact and horizontally regular environments. When toggling between the two environments, only the size of the navigation controller’s view changes. The navigation controller doesn’t change its view hierarchy or the layout of its views.
When configuring segues between view controllers on a navigation stack, the standard Show and Show Detail segues behave as follows:
Show segueThe navigation controller pushes the specified view controller onto its navigation stack.Show Detail segueThe navigation controller presents the specified view controller modally.
The behaviors of other segue types are unchanged.
### Interface behaviors
A navigation controller supports the following behaviors for its interface:
Supported interface orientationsA navigation controller object doesn’t consult the view controllers on its navigation stack when determining the supported interface orientations. On iPhone, a navigation controller supports all orientations except portrait upside-down. On iPad, a navigation controller supports all orientations. If the navigation controller has a delegate object, the delegate can specify a different set of supported orientations using the
[navigationControllerSupportedInterfaceOrientations(_:)](https://developer.apple.com/documentation/uikit/uinavigationcontrollerdelegate/1621884-navigationcontrollersupportedint)
method.Presentation contextA navigation controller defines the presentation context for modally presented view controllers. When the modal transition style is[UIModalPresentationStyle.currentContext](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle/currentcontext)
or[UIModalPresentationStyle.overCurrentContext](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle/overcurrentcontext)
, modal presentations from the view controllers in the navigation stack cover the entire navigation interface.### State preservation
When you assign a value to a navigation controller’s
[restorationIdentifier](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621499-restorationidentifier)
property, it attempts to preserve itself and the child view controllers on its navigation stack. The navigation controller starts at the bottom of the stack and moves upward, encoding each view controller that also has a valid restoration identifier string. During the next launch cycle, the navigation controller restores the preserved view controllers to the navigation stack in the same order that they were preserved.The child view controllers you push onto the navigation stack may use the same restoration identifiers. The navigation controller automatically stores additional information to ensure that each child’s restoration path is unique.
For more information about how state preservation and restoration works, see Preserving your app’s UI across launches.
- If the new top-level view controller has a custom left bar button item, that item is displayed. To specify a custom left bar button item, set the
-
-
ViewController 간의 데이터 전달
## Declaration
func present( _ viewControllerToPresent: [UIViewController](https://developer.apple.com/documentation/uikit/uiviewcontroller), animated flag: [Bool](https://developer.apple.com/documentation/swift/bool), completion: (() -> [Void](https://developer.apple.com/documentation/swift/void))? = nil )
**Parameters**
viewControllerToPresent
The view controller to display over the current view controller’s content.flag
Passtrue
to animate the presentation; otherwise, passfalse
.completion
The block to execute after the presentation finishes. This block has no return value and takes no parameters. You may specifynil
for this parameter.## **Declaration**
func dismiss( animated flag: [Bool](https://developer.apple.com/documentation/swift/bool), completion: (() -> [Void](https://developer.apple.com/documentation/swift/void))? = nil )
**Parameters
flag
Passtrue
to animate the transition.completion
The block to execute after the view controller is dismissed. This block has no return value and takes no parameters. You may specifynil
for this parameter.현재 컨트롤러에서 이동할 위치의 컨트롤러를 직접 호출해서 화면을 전환하는 방식.
직접 호출(표시)한다는 의미에서 presentation 방식이라 부른다.
기존 viewController위에 새로운 viewController를 덮는 방식
present() 메소드에 이동할 화면의 뷰 컨트롤러를 넘겨주면 이전 화면에서 이동할 화면의 뷰 컨트롤러가 표시된다.
present 메소드의 첫 번째 파라미터엔 이동할 화면의 뷰 컨트롤러 인스턴스를 넘겨주면 되고
두번째 파라미터엔 애니메이션 효과를 줄 건지 안 줄건지 Bool 값으로
마지막 completion엔 클로저를 전달받고 있는데
이 클로저에 코드를 쓰면, 화면 전환이 완료되는 시점에 맞춰 completion 클로저가 호출되게 된다.
화면 전환 방식은 비동기 방식으로 처리되기 때문에 화면 전환이 완료된 이후에 코드로 처리해야할 로직이 있다면 여기에 쓰면 된다.
그리고 present 되었던 화면에서 이전화면으로 돌아가게 해주는 메소드가 있다.
바로 dismiss 메소드!
이 메소드는 이전 화면으로 돌아가는 기능이라 뷰 컨트롤러의 인스턴스를 인자로 받지 않는다.
dismiss 메소드의 첫번째 파라미터는 애니메이션 적용 여부
두 번째는 completion 클로저이다. (마찬가지로 화면 전환 후 동작)
📢 3주차 수업 후기
드디어 헷갈리기 쉬운 부분인 화면 전환과 생명주기가 등장했다.
생명주기가 얽히고 섥힌 부분이 많아서 많이 어렵지만, 한 번 제대로 파악해두잔 심정으로 열심히 파고들었다.
그리고 드디어 코드를 많이 작성하면서 이전에 발생하지 않았던 여러 에러들도 마주했다.
특히 옵셔널에서 많은 어려움을 겪었는데
옵셔널은…어쩔 수 없는 것 같다. 최대한 많이 해봐야지….
⚠️ 스터디간 주의사항
- 과제 피드백 기반 진행입니다 - 한명씩 본인의 과제를 발표하는 시간 그리고 해온 과제에 대한 피드백을 하는 시간 (ex:전 이렇게 생각해서 이런 부분 다르게 해왔는데 저것도 괜찮은 것 같아요!)이 무조건 기반이 되어야 합니다!
- 부가적으로 워크북에서 제공되는 키워드 혹은 강의에서 들은 디테일적인 부분에서 더 토의해봐도 좋을 것 같습니다.
✅ 실습 체크리스트
- AutoLayout을 통해 비율에 맞는 화면을 구성할 수 있나요?
버튼이 엄청 많아서 레이아웃 설정에 상당히 애를 먹었다(딱 봐도 힘들었을 것 같지 않니요)
- 주요 UI 컴포넌트의 속성, 속성을 변경하는 방법에 대해 이해하고 실습을 진행했나요?
실제 시뮬을 돌려보면 이렇게 나온다
모두 속성(radius)을 변화시켜 버튼을 변화시켰다
- IBOutlet, IBAction을 통해 뷰에 액션을 연결할 수 있나요?
계산기 화면의 과정 화면이라던지 그 다음 화면의 정답 라벨을 그리고 백버튼의 액션까지 정의했다
- Optional Unwrapping을 사용하여 Optional 값을 안전하게 가져올 수 있나요?
guard let 활용
타입 캐스팅까지
-
present를 통해 화면 전환을 할 수 있나요?
-
SecondViewController에게 데이터를 전달할 수 있나요?
-
미션 참고 영상
⚡ 트러블 슈팅
-
⚡이슈 No.1 (예시, 서식만 복사하시고 지워주세요.)
이슈
👉 앱 실행 중에 노래 다음 버튼을 누르니까 앱이 종료되었다.
문제
👉 노래클래스의 데이터리스트의 Size를 넘어서 NullPointException이 발생하여 앱이 종료된 것이었다.
해결
👉 노래 다음 버튼을 눌렀을 때 데이터리스트의 Size를 검사해 Size보다 넘어가려고 하면 다음으로 넘어가는 메서드를 실행시키지 않고, 첫 노래로 돌아가게끔 해결
참고레퍼런스
- 링크
🤔 이것도 한 번 생각해봐요!
- ViewController의 생명 주기 함수를 모두 사용해보세요!
- SceneDelegate(앱의 생명주기)에 대해 공부해보세요!
-
sceneDidDisconnect 함수는 언제 실행 될까요?
-
sceneDidBecomeActive 함수는 언제 실행 될까요?
-
sceneWillResignActive 함수는 언제 실행 될까요?
-
sceneWillEnterForeground 함수는 언제 실행 될까요?
-
sceneDidEnterBackground 함수는 언제 실행 될까요?
-
-
화면의 전환에도 애니메이션을 선택할 수 있다?! 다음 화면의 보여주는 방식도 선택할 수 있다?!
Hint. OOOOViewController().~~~~~style
- 화면 전환에서 FullScreen과 FormSheet의 차이는 뭘까요?
- ViewController 간의 데이터 전달에는 여러가지 방법이 있어요! 각 방법은 어떤 경우에 사용하면 좋을까요?
🎛 라이프 사이클
View에게 생명주기는 무슨 의미일까?
화면은 보여졌다가 사라지는 즉 탄생하고 소멸하기까지 한 사이클을 말한다.
총 8 단계로 전부 외울 필요 없음
애플에서 세분화시킨 라이프사이클
init: 신생아가 태어나는 순간(뷰가 탄생하는 순간)
loadView: 태어나서 태어났다고 들을 때
viewDidLoad: (중요) 이 8가지 각각 단계는 스윽 봐도
이 viewDidLoad는 뷰 계층이 최초 메모리에 로드된 후 호출되는 메서드 메모리에 처음 로딩 될 때 1회만 호출됨
애기가 태어나서 출생 신고를 할 때
-라이프사이클의 탄생 배경: 모바일에서는 화면 별 역할이 구성되어있어서(단계를 나누어 화면을 쪼개서 진행해서) ↔ 데스크탑과는 다르다!
그래서 뷰의 전환이 잦게 되어, 생명주기를 다루게 됨
😇 생명주기
😩내가 헷갈렸던 거
SceneDelegate에 있는 화면 전환 관련 함수들
SceneWillEnterForeground
sceneDidBecomeActive (앱 실행하면 여기까지)
scenewillResignActive. (앱이 곧 비활성화 될거야)
sceneDidDisconnect (앱이 꺼지는 순간에)
sceneDidEnterBackground (앱이 백그라운드 상태에 진입)
🎯 핵심 키워드
- ViewController Life Cycle
-
loadView
You should never call this method directly. The view controller calls this method when its
[view](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621460-view)
property is requested but is currentlynil
. This method loads or creates a view and assigns it to the[view](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621460-view)
property.If the view controller has an associated nib file, this method loads the view from the nib file. A view controller has an associated nib file if the
[nibName](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621487-nibname)
property returns a non-nil
value, which occurs if the view controller was instantiated from a storyboard, if you explicitly assigned it a nib file using the[init(nibName:bundle:)](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621359-init)
method, or if iOS finds a nib file in the app bundle with a name based on the view controller’s class name. If the view controller does not have an associated nib file, this method creates a plain[UIView](https://developer.apple.com/documentation/uikit/uiview)
object instead.If you use Interface Builder to create your views and initialize the view controller, you must not override this method.
You can override this method in order to create your views manually. If you choose to do so, assign the root view of your view hierarchy to the
[view](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621460-view)
property. The views you create should be unique instances and should not be shared with any other view controller object. Your custom implementation of this method should not callsuper
.If you want to perform any additional initialization of your views, do so in the
[viewDidLoad()](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621495-viewdidload)
method. -
viewDidLoad
You can override this method to perform tasks to immediately follow the setting of the
[view](https://developer.apple.com/documentation/appkit/nsviewcontroller/1434401-view)
property.Typically, your override would perform one-time instantiation and initialization of the contents of the view controller’s view. If you override this method, call this method on
super
at some point in your implementation in case a superclass also overrides this method.For a view controller originating in a nib file, this method is called immediately after the
[view](https://developer.apple.com/documentation/appkit/nsviewcontroller/1434401-view)
property is set. For a view controller created programmatically, this method is called immediately after the[loadView()](https://developer.apple.com/documentation/appkit/nsviewcontroller/1434405-loadview)
method completes.The default implementation of this method does nothing.
-
viewWillAppear
This method is called before the view controller’s view is about to be added to a view hierarchy and before any animations are configured for showing the view. You can override this method to perform custom tasks associated with displaying the view. For example, you might use this method to change the orientation or style of the status bar to coordinate with the orientation or style of the view being presented. If you override this method, you must call
super
at some point in your implementation.For more information about the how views are added to view hierarchies by a view controller, and the sequence of messages that occur, see Supporting Accessibility.
-
viewDidAppear
You can override this method to perform additional tasks associated with presenting the view. If you override this method, you must call
super
at some point in your implementation. -
viewWillDisappear
This method is called in response to a view being removed from a view hierarchy. This method is called before the view is actually removed and before any animations are configured.
Subclasses can override this method and use it to commit editing changes, resign the first responder status of the view, or perform other relevant tasks. For example, you might use this method to revert changes to the orientation or style of the status bar that were made in the
[viewDidAppear(_:)](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621423-viewdidappear)
method when the view was first presented. If you override this method, you must callsuper
at some point in your implementation. -
viewDidDisappear
You can override this method to perform additional tasks associated with dismissing or hiding the view. If you override this method, you must call
super
at some point in your implementation.
-
-
Optional
## Declaration
@frozen enum Optional<Wrapped>
## Overview
You use the
Optional
type whenever you use optional values, even if you never type the wordOptional
. Swift’s type system usually shows the wrapped type’s name with a trailing question mark (?
) instead of showing the full type name. For example, if a variable has the typeInt?
, that’s just another way of writingOptional<Int>
. The shortened form is preferred for ease of reading and writing code.The types of
shortForm
andlongForm
in the following code sample are the same:let shortForm: Int? = Int("42")let longForm: Optional<Int> = Int("42")
The
Optional
type is an enumeration with two cases.Optional.none
is equivalent to thenil
literal.Optional.some(Wrapped)
stores a wrapped value. For example:let number: Int? = Optional.some(42)let noNumber: Int? = Optional.noneprint(noNumber == nil)// Prints "true"
You must unwrap the value of an
Optional
instance before you can use it in many contexts. Because Swift provides several ways to safely unwrap optional values, you can choose the one that helps you write clear, concise code.The following examples use this dictionary of image names and file paths:
let imagePaths = ["star": "/glyphs/star.png", "portrait": "/images/content/portrait.jpg", "spacer": "/images/shared/spacer.gif"]
Getting a dictionary’s value using a key returns an optional value, so
imagePaths["star"]
has typeOptional<String>
or, written in the preferred manner,String?
.## Optional Binding
To conditionally bind the wrapped value of an
Optional
instance to a new variable, use one of the optional binding control structures, includingif let
,guard let
, andswitch
.if let starPath = imagePaths["star"] { print("The star image is at '\(starPath)'")} else { print("Couldn't find the star image")}// Prints "The star image is at '/glyphs/star.png'"
## Optional Chaining
To safely access the properties and methods of a wrapped instance, use the postfix optional chaining operator (postfix
?
). The following example uses optional chaining to access thehasSuffix(_:)
method on aString?
instance.if imagePaths["star"]?.hasSuffix(".png") == true { print("The star image is in PNG format")}// Prints "The star image is in PNG format"
## Using the Nil-Coalescing Operator
Use the nil-coalescing operator (
??
) to supply a default value in case theOptional
instance isnil
. Here a default path is supplied for an image that is missing fromimagePaths
.let defaultImagePath = "/images/default.png"let heartPath = imagePaths["heart"] ?? defaultImagePathprint(heartPath)// Prints "/images/default.png"
The
??
operator also works with anotherOptional
instance on the right-hand side. As a result, you can chain multiple??
operators together.let shapePath = imagePaths["cir"] ?? imagePaths["squ"] ?? defaultImagePathprint(shapePath)// Prints "/images/default.png"
## Unconditional Unwrapping
When you’re certain that an instance of
Optional
contains a value, you can unconditionally unwrap the value by using the forced unwrap operator (postfix!
). For example, the result of the failableInt
initializer is unconditionally unwrapped in the example below.let number = Int("42")!print(number)// Prints "42"
You can also perform unconditional optional chaining by using the postfix
!
operator.let isPNG = imagePaths["star"]!.hasSuffix(".png")print(isPNG)// Prints "true"
Unconditionally unwrapping a
nil
instance with!
triggers a runtime error. -
Optional Binding
## Optional Binding
To conditionally bind the wrapped value of an
Optional
instance to a new variable, use one of the optional binding control structures, includingif let
,guard let
, andswitch
.if let starPath = imagePaths["star"] { print("The star image is at '\(starPath)'")} else { print("Couldn't find the star image")}// Prints "The star image is at '/glyphs/star.png'"
-
Optional Chaining
## Optional Chaining
To safely access the properties and methods of a wrapped instance, use the postfix optional chaining operator (postfix
?
). The following example uses optional chaining to access thehasSuffix(_:)
method on aString?
instance.if imagePaths["star"]?.hasSuffix(".png") == true { print("The star image is in PNG format")}// Prints "The star image is in PNG format"
-
Forced Unwrapping
강제로 옵셔널 벗겨내기 → ! 사용
-
guard문
guard let (옵셔널 바인딩일 때)
- 옵셔널을 벗겼을 때 nil이면 더 이상 코드를 실행시키지 않겠다는 의미가 강함 -> nil이 아닐 때만 관심을 갖겠다.
- 선언된 변수를 아래문장에서 사용 가능 (동일한 스코프로 취급)
guard 조건 else { // 조건이 false 이면 else 구문이 실행되고return or throw or break 를 통해 이 후 코드를 실행하지 않도록 한다. }
간단하게 설명하자면 아래와 같이 말 할 수 있을 것입니다!
- 뭔가를 검사하여 그 다음에 오는 코드를 실행할지 말지 결정 하는 것
- guard 문에 주어진 조건문이 거짓일 때 구문이 실행됨
- 화면 전환
-
present
## Declaration
func present( _ viewControllerToPresent: [UIViewController](https://developer.apple.com/documentation/uikit/uiviewcontroller), animated flag: [Bool](https://developer.apple.com/documentation/swift/bool), completion: (() -> [Void](https://developer.apple.com/documentation/swift/void))? = nil )
**Parameters**
viewControllerToPresent
The view controller to display over the current view controller’s content.flag
Passtrue
to animate the presentation; otherwise, passfalse
.completion
The block to execute after the presentation finishes. This block has no return value and takes no parameters. You may specifynil
for this parameter. -
Navigation Controller
## Declaration
@MainActor class UINavigationController : UIViewController
## Overview
A navigation controller is a container view controller that manages one or more child view controllers in a navigation interface. In this type of interface, only one child view controller is visible at a time. Selecting an item in the view controller pushes a new view controller onscreen using an animation, hiding the previous view controller. Tapping the back button in the navigation bar at the top of the interface removes the top view controller, thereby revealing the view controller underneath.
Use a navigation interface to mimic the organization of hierarchical data managed by your app. At each level of the hierarchy, you provide an appropriate screen (managed by a custom view controller) to display the content at that level. The following image shows an example of the navigation interface presented by the Settings application in iOS Simulator. The first screen presents the user with the list of applications that contain preferences. Selecting an application reveals individual settings and groups of settings for that application. Selecting a group yields more settings and so on. For all but the root view, the navigation controller provides a back button to allow the user to move back up the hierarchy.
A navigation controller object manages its child view controllers using an ordered array, known as the navigation stack. The first view controller in the array is the root view controller and represents the bottom of the stack. The last view controller in the array is the topmost item on the stack, and represents the view controller currently being displayed. You add and remove view controllers from the stack using segues or using the methods of this class. The user can also remove the topmost view controller using the back button in the navigation bar or using a left-edge swipe gesture.
The navigation controller manages the navigation bar at the top of the interface and an optional toolbar at the bottom of the interface. The navigation bar is always present and is managed by the navigation controller itself, which updates the navigation bar using the content provided by its child view controllers. When the
[isToolbarHidden](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621875-istoolbarhidden)
property isfalse
, the navigation controller similarly updates the toolbar with contents provided by the topmost view controller.A navigation controller coordinates its behavior with its
[delegate](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621876-delegate)
object. The delegate object can override the pushing or popping of view controllers, provide custom animation transitions, and specify the preferred orientation for the navigation interface. The delegate object you provide must conform to the[UINavigationControllerDelegate](https://developer.apple.com/documentation/uikit/uinavigationcontrollerdelegate)
protocol.The following image shows the relationships between the navigation controller and the objects it manages. Use the specified properties of the navigation controller to access these objects.
### Navigation controller views
A navigation controller is a container view controller — that is, it embeds the content of other view controllers inside of itself. You access a navigation controller’s view from its
[view](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621460-view)
property. This view incorporates the navigation bar, an optional toolbar, and the content view corresponding to the topmost view controller. The following image shows how these views are assembled to present the overall navigation interface. (In this figure, the navigation interface is further embedded inside a tab bar interface.) Although the content of the navigation bar and toolbar views changes, the views themselves don’t. The only view that actually changes is the custom content view provided by the topmost view controller on the navigation stack.Note Because the content view underlaps the navigation bar in iOS 7 and later, you must consider that space when designing your view controller content.
The navigation controller manages the creation, configuration, and display of the navigation bar and optional navigation toolbar. It’s permissible to customize the navigation bar’s appearance-related properties but you must never change its
[frame](https://developer.apple.com/documentation/uikit/uiview/1622621-frame)
,[bounds](https://developer.apple.com/documentation/uikit/uiview/1622580-bounds)
, or[alpha](https://developer.apple.com/documentation/uikit/uiview/1622417-alpha)
values directly. If you subclassUINavigationBar
, you must initialize your navigation controller using the[init(navigationBarClass:toolbarClass:)](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621866-init)
method. To hide or show the navigation bar, use the[isNavigationBarHidden](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621850-isnavigationbarhidden)
property or[setNavigationBarHidden(_:animated:)](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621885-setnavigationbarhidden)
method.A navigation controller builds the contents of the navigation bar dynamically using the navigation item objects (instances of the
[UINavigationItem](https://developer.apple.com/documentation/uikit/uinavigationitem)
class) associated with the view controllers on the navigation stack. To customize the overall appearance of a navigation bar, use[UIAppearance](https://developer.apple.com/documentation/uikit/uiappearance)
APIs. To change the contents of the navigation bar, you must therefore configure the navigation items of your custom view controllers. For more information about navigation items, see[UINavigationItem](https://developer.apple.com/documentation/uikit/uinavigationitem)
.### Updating the navigation bar
Each time the top-level view controller changes, the navigation controller updates the navigation bar accordingly. Specifically, the navigation controller updates the bar button items displayed in each of the three navigation bar positions: left, middle, and right. Bar button items are instances of the
[UIBarButtonItem](https://developer.apple.com/documentation/uikit/uibarbuttonitem)
class. You can create items with custom content or create standard system items depending on your needs.Tinting of the navigation bar is controlled by properties of the navigation bar itself. Use the
[tintColor](https://developer.apple.com/documentation/uikit/uinavigationbar/1624937-tintcolor)
property to change the tint color of items in the bar and use the[barTintColor](https://developer.apple.com/documentation/uikit/uinavigationbar/1624931-bartintcolor)
property to change the tint color of the bar itself. Navigation bars don’t inherit their tint color from the currently displayed view controller.For more information about the navigation bar, see
[UINavigationBar](https://developer.apple.com/documentation/uikit/uinavigationbar)
. For more information about how to create bar button items, see[UIBarButtonItem](https://developer.apple.com/documentation/uikit/uibarbuttonitem)
.### The left item
For all but the root view controller on the navigation stack, the item on the left side of the navigation bar provides navigation back to the previous view controller. The contents of this left-most button are determined as follows:
- If the new top-level view controller has a custom left bar button item, that item is displayed. To specify a custom left bar button item, set the
[leftBarButtonItem](https://developer.apple.com/documentation/uikit/uinavigationitem/1624936-leftbarbuttonitem)
property of the view controller’s navigation item. - If the top-level view controller doesn’t have a custom left bar button item, but the navigation item of the previous view controller has an object in its
[backBarButtonItem](https://developer.apple.com/documentation/uikit/uinavigationitem/1624958-backbarbuttonitem)
property, the navigation bar displays that item. - If a custom bar button item isn’t specified by either of the view controllers, a default back button is used and its title is set to the value of the
[title](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621364-title)
property of the previous view controller — that is, the view controller one level down on the stack. (If there’s only one view controller on the navigation stack, no back button is displayed.)
Note In cases where the title of a back button is too long to fit in the available space, the navigation bar may substitute the string “Back” for the actual button title. The navigation bar does this only if the back button is provided by the previous view controller. If the new top-level view controller has a custom left bar button item — an object in the
[leftBarButtonItem](https://developer.apple.com/documentation/uikit/uinavigationitem/1624936-leftbarbuttonitem)
or[leftBarButtonItems](https://developer.apple.com/documentation/uikit/uinavigationitem/1624946-leftbarbuttonitems)
property of its navigation item—the navigation bar doesn’t change the button title.### The middle item
The navigation controller updates the middle of the navigation bar as follows:
- If the new top-level view controller has a custom title view, the navigation bar displays that view in place of the default title view. To specify a custom title view, set the
[titleView](https://developer.apple.com/documentation/uikit/uinavigationitem/1624935-titleview)
property of the view controller’s navigation item. - If no custom title view is set, the navigation bar displays a label containing the view controller’s default title. The string for this label is usually obtained from the
[title](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621364-title)
property of the view controller itself. If you want to display a different title than the one associated with the view controller, set thetitle
property of the view controller’s navigation item instead.
### The right item
The navigation controller updates the right side of the navigation bar as follows:
- If the new top-level view controller has a custom right bar button item, that item is displayed. To specify a custom right bar button item, set the
[rightBarButtonItem](https://developer.apple.com/documentation/uikit/uinavigationitem/1624957-rightbarbuttonitem)
property of the view controller’s navigation item. - If no custom right bar button item is specified, the navigation bar displays nothing on the right side of the bar.
### Displaying a toolbar
A navigation controller object manages an optional toolbar in its view hierarchy. When displayed, this toolbar obtains its current set of items from the
[toolbarItems](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621867-toolbaritems)
property of the active view controller. When the active view controller changes, the navigation controller updates the toolbar items to match the new view controller, animating the new items into position when appropriate.The navigation toolbar is hidden by default but you can show it for your navigation interface by calling the
[setToolbarHidden(_:animated:)](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621888-settoolbarhidden)
method of your navigation controller object. If not all of your view controllers support toolbar items, your delegate object can call this method to toggle the visibility of the toolbar during subsequent push and pop operations. To use a customUIToolbar
subclass, initialize the navigation controller using the[init(navigationBarClass:toolbarClass:)](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621866-init)
method. If you use custom toolbar and navigation bar subclasses to create a navigation controller, note that you’re responsible for pushing and setting view controllers before presenting the navigation controller onscreen.### Adapting to different environments
The navigation interface remains the same in both horizontally compact and horizontally regular environments. When toggling between the two environments, only the size of the navigation controller’s view changes. The navigation controller doesn’t change its view hierarchy or the layout of its views.
When configuring segues between view controllers on a navigation stack, the standard Show and Show Detail segues behave as follows:
Show segueThe navigation controller pushes the specified view controller onto its navigation stack.Show Detail segueThe navigation controller presents the specified view controller modally.
The behaviors of other segue types are unchanged.
### Interface behaviors
A navigation controller supports the following behaviors for its interface:
Supported interface orientationsA navigation controller object doesn’t consult the view controllers on its navigation stack when determining the supported interface orientations. On iPhone, a navigation controller supports all orientations except portrait upside-down. On iPad, a navigation controller supports all orientations. If the navigation controller has a delegate object, the delegate can specify a different set of supported orientations using the
[navigationControllerSupportedInterfaceOrientations(_:)](https://developer.apple.com/documentation/uikit/uinavigationcontrollerdelegate/1621884-navigationcontrollersupportedint)
method.Presentation contextA navigation controller defines the presentation context for modally presented view controllers. When the modal transition style is[UIModalPresentationStyle.currentContext](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle/currentcontext)
or[UIModalPresentationStyle.overCurrentContext](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle/overcurrentcontext)
, modal presentations from the view controllers in the navigation stack cover the entire navigation interface.### State preservation
When you assign a value to a navigation controller’s
[restorationIdentifier](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621499-restorationidentifier)
property, it attempts to preserve itself and the child view controllers on its navigation stack. The navigation controller starts at the bottom of the stack and moves upward, encoding each view controller that also has a valid restoration identifier string. During the next launch cycle, the navigation controller restores the preserved view controllers to the navigation stack in the same order that they were preserved.The child view controllers you push onto the navigation stack may use the same restoration identifiers. The navigation controller automatically stores additional information to ensure that each child’s restoration path is unique.
For more information about how state preservation and restoration works, see Preserving your app’s UI across launches.
- If the new top-level view controller has a custom left bar button item, that item is displayed. To specify a custom left bar button item, set the
-
-
ViewController 간의 데이터 전달
## Declaration
func present( _ viewControllerToPresent: [UIViewController](https://developer.apple.com/documentation/uikit/uiviewcontroller), animated flag: [Bool](https://developer.apple.com/documentation/swift/bool), completion: (() -> [Void](https://developer.apple.com/documentation/swift/void))? = nil )
**Parameters**
viewControllerToPresent
The view controller to display over the current view controller’s content.flag
Passtrue
to animate the presentation; otherwise, passfalse
.completion
The block to execute after the presentation finishes. This block has no return value and takes no parameters. You may specifynil
for this parameter.## **Declaration**
func dismiss( animated flag: [Bool](https://developer.apple.com/documentation/swift/bool), completion: (() -> [Void](https://developer.apple.com/documentation/swift/void))? = nil )
**Parameters
flag
Passtrue
to animate the transition.completion
The block to execute after the view controller is dismissed. This block has no return value and takes no parameters. You may specifynil
for this parameter.현재 컨트롤러에서 이동할 위치의 컨트롤러를 직접 호출해서 화면을 전환하는 방식.
직접 호출(표시)한다는 의미에서 presentation 방식이라 부른다.
기존 viewController위에 새로운 viewController를 덮는 방식
present() 메소드에 이동할 화면의 뷰 컨트롤러를 넘겨주면 이전 화면에서 이동할 화면의 뷰 컨트롤러가 표시된다.
present 메소드의 첫 번째 파라미터엔 이동할 화면의 뷰 컨트롤러 인스턴스를 넘겨주면 되고
두번째 파라미터엔 애니메이션 효과를 줄 건지 안 줄건지 Bool 값으로
마지막 completion엔 클로저를 전달받고 있는데
이 클로저에 코드를 쓰면, 화면 전환이 완료되는 시점에 맞춰 completion 클로저가 호출되게 된다.
화면 전환 방식은 비동기 방식으로 처리되기 때문에 화면 전환이 완료된 이후에 코드로 처리해야할 로직이 있다면 여기에 쓰면 된다.
그리고 present 되었던 화면에서 이전화면으로 돌아가게 해주는 메소드가 있다.
바로 dismiss 메소드!
이 메소드는 이전 화면으로 돌아가는 기능이라 뷰 컨트롤러의 인스턴스를 인자로 받지 않는다.
dismiss 메소드의 첫번째 파라미터는 애니메이션 적용 여부
두 번째는 completion 클로저이다. (마찬가지로 화면 전환 후 동작)
📢 3주차 수업 후기
드디어 헷갈리기 쉬운 부분인 화면 전환과 생명주기가 등장했다.
생명주기가 얽히고 섥힌 부분이 많아서 많이 어렵지만, 한 번 제대로 파악해두잔 심정으로 열심히 파고들었다.
그리고 드디어 코드를 많이 작성하면서 이전에 발생하지 않았던 여러 에러들도 마주했다.
특히 옵셔널에서 많은 어려움을 겪었는데
옵셔널은…어쩔 수 없는 것 같다. 최대한 많이 해봐야지….
스탠다드 미션
계산기 앱을 화면 전환을 통해 구현하기
사실 처음에는 ios의 기본 계산기처럼 UI를 구성하고 식의 과정만을 메인 화면에 보여주고, 그 다음으로 넘어가는 화면에 값을 넘기자는 계획을 했었으나
예상보다 계산기 만들기가 상당히 재미진 나머지, 진짜 계산기처럼 값이 메인 화면에 나온 다음, 이 값을 다시 다음 화면에 전달해보았다.
1.제일 먼저 버튼 레이아웃 만들기 각 라벨에 숫자를 지정하고, 줄에 맞춰 오토 레이아웃을 맞췄다.
이 과정은…너무도 힘들었기에 (사실 너무 화가 나서) 레이아웃 과정을 일일히 뜨지 못했다.
단지 width와 Ratio를 활용해서 저 바둑판을 만들어냈다는 것만 기억하자
- 계산기 기능 구현
import UIKit
enum Operation {
case Add
case Subtract
case Divide
case Multiply
case unknown
}
class ViewController: UIViewController {
@IBOutlet weak var numberOutputLabel: UILabel!
var displayNumber = ""
var firstOperand = ""
var secondOperand = ""
var result = ""
var currentOperation: Operation = .unknown
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func tapNumberButton(_ sender: UIButton) {
guard let numberValue = sender.titleLabel?.text else { return }
if self.displayNumber.count < 9 {
self.displayNumber += numberValue
self.numberOutputLabel.text = self.displayNumber
}
}
@IBAction func tapClearButton(_ sender: UIButton) {
self.displayNumber = ""
self.firstOperand = ""
self.secondOperand = ""
self.result = ""
self.currentOperation = .unknown
self.numberOutputLabel.text = "0"
}
@IBAction func tapDotButton(_ sender: UIButton) {
if self.displayNumber.count < 8, !self.displayNumber.contains(".") {
self.displayNumber += self.displayNumber.isEmpty ? "0." : "."
self.numberOutputLabel.text = self.displayNumber
}
}
@IBAction func tapDivideButton(_ sender: UIButton) {
self.operation(.Divide)
}
@IBAction func tapMultiplyButton(_ sender: UIButton) {
self.operation(.Multiply)
}
@IBAction func tapSubtractButton(_ sender: UIButton) {
self.operation(.Subtract)
}
@IBAction func tapAddButton(_ sender: UIButton) {
self.operation(.Add)
}
@IBAction func tapEqualButton(_ sender: UIButton) {
self.operation(self.currentOperation)
guard let OutcomeViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "OutcomeViewController") as? OutcomeViewController else {return}
OutcomeViewController.result = self.result
// 이동할 뷰 컨트롤러의 아이디를 지정해, 인스턴스화 하는 것->인스턴스화 해야지 pushViewController메소드에 넣을 수 있다
present(OutcomeViewController, animated: true)
}
func operation(_ operation: Operation){
if self.currentOperation != .unknown {
if !self.displayNumber.isEmpty {
self.secondOperand = self.displayNumber
self.displayNumber = ""
guard let firstOperand = Double(self.firstOperand) else {return}
guard let secondOperand = Double(self.secondOperand) else {return}
switch self.currentOperation {
case .Add:
self.result = "\(firstOperand + secondOperand)"
case .Subtract:
self.result = "\(firstOperand - secondOperand)"
case .Divide:
self.result = "\(firstOperand / secondOperand)"
case .Multiply:
self.result = "\(firstOperand * secondOperand)"
default:
break
}
self.firstOperand = self.result
self.numberOutputLabel.text = self.result
}
self.currentOperation = operation
} else {
self.firstOperand = self.displayNumber
self.currentOperation = operation
self.displayNumber = ""
}
}
}
enum을 사용해서 각 오퍼레이션을 구분했다.
이게 더 깔끔하기도 하고, 모든 계산을 operation함수 하나로 퉁치고 싶었기 때문이다.
3.오늘의 주안점 present 방식으로 넘어가는 코드
다음 뷰 컨트롤러에 있는 result 변수에 여기 영역의 result 값을 넘겨주고 있다.
그럼 그쪽 result가 viewDidLoad에서 라벨에 표시되는 코드가 실행된다.
🎯 프로블럼 이슈 이, 이게 뭐여
생전 처음보는 에러가 뜨길래 조사해보니
코코아팟에 문제가 생겼다는 것 같았다.
[Solution 1] podfile에 다음의 코드를 추가하기
# Workaround for Cocoapods issue #7606
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
config.build_settings.delete('CODE_SIGNING_ALLOWED')
config.build_settings.delete('CODE_SIGNING_REQUIRED')
end
end
[Solution 2] 기존 Cocoapads를 지우고 1.4.x 버전 cocoapads 설치
다음의 코드를 terminal에서 차례대로 입력합니다.
pod update는 podfile을 포함하고 있는 프로젝트로 경로를 이동해서 입력합니다.
sudo gem uninstall cocoapods
sudo gem install cocoapods -v 1.4.0
pod update
댓글남기기