va95 2021. 2. 21. 00:09

학습 내용

 

View Controller의 생명주기

ViewController는 생명주기를 가지고 있으며, 이는 ViewController가 생성되고 사라지는 전 과정에서 ViewController에게 전달되는 일련의 메시지입니다.

우리는 통상 생명주기와 연결된 메소드들을 override를 통해서 재정의하고 특정 시점에 원하는 코드를 실행할 수 있게 됩니다.

보통 View Controller는 스토리보드로 구성하게 되며, 몇몇의 특수한 뷰 컨트롤러(ex. 카메라) 등은 코드로 API를 통해서 불러올 수도 있습니다. 

 

ViewDidLoad

화면이 초기할때 자주 사용됩니다. 현재의 outlet들이 셋팅되어 있기 때문에 Model을 사용하는 뷰를 업데이트 하기에 아주 좋습니다.

하지만 Bounds와 관련된 것들을 조작해서는 안됩니다.

아직 셋팅이 되기 전임으로 여러분이 원하는 결과를 기대할 수 없을지도 모릅니다.

단 한번만 호출 됩니다.

 

ViewWillAppear

MVC가 화면에 나타나기 직전에 호출되는 메소드 입니다.

모델이 네트워크 상에 있다면, 최신의 데이터를 유지할 때 사용됩니다.

반복적으로 호출 될 수 있습니다.

 

ViewDidAppear

화면에 나타난 후에 호출됩니다.

타이머, 애니메이션, GPS와 같은 것들을 구현하면 좋습니다.

비교적 비용이 큰(시간, 배터리, 저장용량) 작업들을 수행하기에 적절합니다. 

 

ViewWillDisappear

MVC가 화면에 있고 곧 사라질 예정일때 사용하게 됩니다.

ViewDidAppear에서 구현했던 다양한 기능들을 최초의 상태로 돌리기에 적절한 순간입니다. 

 

ViewDidDisappear

상태를 저장하거나, MVC를 저장하는 데에 쓰이지만 대부분 잘 쓰이지 않습니다.

 

*ViewWillLayoutSubViews, ViewDidLayoutSubViews

뷰 컨트롤러의 view가 layoutSubviews 메소드를 호출 받기 전후로 위의 함수를 호출합니다.

view에 서브뷰가 추가, 삭제 될 때 혹은 경계가 바뀔 때 혹은 시스템이 레이아웃을 알고자 할 때 호출됩니다.

애니메이션의 종료 시점에서의 레이아웃도 알아야하기 때문에, 시스템이 이 함수를 호출할 수도 있습니다.

즉, 변경사항이 없더라도 시스템 자체적으로 레이아웃을 얻기 위해 호출할 수도 있어서, 꼭 이 함수가 view의 변화를 뜻하진 않습니다.

 

Geometry와 관련된 것은 viewWillLayoutSubViews(), viewDidLayoutSubviews()에서 구현해 주도록 합니다.(최상위 view의 bounds가 바뀌게 되면 우리는 바뀌었다는 알림을 받게 됩니다.)

통상 autoLayout을 통해 레이아웃들을 재배치하므로 실제로 구현할 필요는 없습니다.(오토레이아웃을 이용하지 않는다면 위의 함수에서 내용을 구현해주면 됩니다.)

 

*ViewWillTransition(Auto Rotation)

이 함수는 기기를 회전시키거나, bounds를 변경할 때 호출됩니다.(물론 layoutSubviews 또한 호출됩니다.)

뷰들의 transition을 이 함수에서 구현할 수 있습니다.

여기서 coordinator 인수와 animate함수를 통해서 transition을 구현할 수 있습니다.(자세한 건 문서를 참고하시기 바랍니다.)

 

*didReceiveMemoryWarning(Low Memory)

만약 힙에 너무 많은 strong 참조를 하고 있다면 메모리가 부족해질 수도 있습니다.(ex. 비디오)

메모리가 부족해지면 iOS 시스템은 자동적으로 해당 함수를 호출하며, 여기서 사용되진 않지만 메모리를 많이 사용하는 리소스를 해제합니다.

그렇지 않다면 iOS 시스템이 강제적으로 앱을 종료시킬 수 있습니다.

 

AwakeFromNib()

스토리보드는 XIB파일로 편집하고(xml 형식) -> 빌드 시 NIB파일로 저장합니다.(코드로 스토리보드를 저장하는 것보다 인코딩 방식을 사용해서 용량을 줄이는 기법이라고 합니다.) -> 앱을 실행하고 해당 NIB파일을 사용할 필요가 생기면 init(coder)를 통해 NIB파일을 디코딩합니다.

이렇게 객체가 생성되면 위의 함수가 호출됩니다.(따라서 스토리보드로부터 만들어진 모든 객체가 해당됩니다.)

아울렛이 설정되기 전, 세그를 준비하기 전에 구현되는 부분이며, 앱 시작의 아주 초기단계이므로, 적절한 코드를 입력해야 할 것입니다.

 

 

순서는 다음과 같습니다.

1. Instantiated

(2. awakeFromNib)

3. segue prepare

4. outlets get set

5. ViewDidLoad

6. viewWillAppear and viewDidAppear + viewWillDisappear and viewDidDisappear

viewDidLoad 이후 언제든 화면이 변화되는 것에 대한 ViewwillLayoutSubviews와 viewDidLayoutSubvies가 호출 됩니다.

메모리가 낮아지게 되면 언제든 didReceiveMemoryWarning이 호출됩니다.

 

타입의 이름 얻는 방법

String(describing: type(of: T)) 함수를 이용하면 타입 이름 그대로 String을 얻을 수 있습니다.


Scroll View

스크롤뷰에서 가장 중요한 것은 컨텐츠 사이즈에 대한 이해입니다.

 

컨텐츠 사이즈가 따로 있고, 이것을 아이폰 스크린이라는 창문을 통해서 바라 본다고 생각하면 이해가 쉬울 것입니다.

컨텐츠 사이즈는 크기(너비와 높이)만 지정해주면 됩니다.

 

만들기 위해서는 스토리보드 또는 UIScrollView(frame:)에서 사용합니다.

또는 여러분의 스토리보드에서 UIView를 선택하여 에디터메뉴에서 Embed In 시키게 되면 여러분이 원하는 결과를 얻을 수 있습니다.(단 약간의 테두리가 생기므로 보정해야합니다.)

 

addSubview를 사용해서 여러분이 원하는 하위 view들을 추가할 수 있습니다.

물론 contentSize를 설정하는 것을 잊게 된다면, 스크롤을 못할 수도 있습니다.(default는 크기가 (0, 0)이기 때문입니다.)

 

스크롤뷰가 현재 컨텐츠 뷰의 어디 위치에 있는지 알려주는 변수입니다. (컨텐츠 뷰에서의 origin을 알려줍니다.)

 

현재 스크롤뷰가 보여주고 있는 좌표계를 반환합니다.

 

스크롤뷰를 스크롤링하는 것을 프로그래밍으로 구현할 수 있습니다.(사용자가 스크롤을 하는 것이 아닌)

Func scrollRectToVisible(CGRect, animated: Bool)을 이용하면 해당 위치로 이동합니다.

 

스크롤링의 가능 여부를 결정할 수 있고, 방향을 고정하거나 스크롤 자체에 효과를 주는 등 다양한 기능들이 구현되어 있습니다.

특히 스크롤뷰는 매우 똑똑하게 구현되어있는데, Safe Area(= 네비게이션 바, 탭 바 등을 제외한 영역)에 정확히 동작합니다.

예를 들어 스크롤뷰를 탭바와 겹치도록 설정해놓고 스크롤을 마지막까지 내린다면, 스크롤을 더 내릴 수 있게 만들어 마지막 컨텐츠까지 탭 바에 가려지지 않고 보일 수 있게 구현되어 있습니다.

 

줌인/줌아웃을 설정하게 되면 컨텐츠 사이즈도 늘어나고/ 줄어듭니다.(transform을 이용합니다.)

스크롤뷰가 자동적으로 contentOffset 위치를 재조정하여 보여줍니다.

이를 구현하기 위해서는 반드시 scrollView.minimumZoomScale, scrollView.maximumZoomScale을 구현해야 합니다.

또한, delegate 프로토콜을 채택 후, viewForZooming(in scrollView: UIScrollView) -> UIView 메소드를 구현해야합니다.

zoom을 하면 컨텐츠 사이즈에 늘어나는 것에 맞춰서 하위 뷰들도 늘어날 필요가 있기 때문에 늘어나야하는 하위 뷰를 알려주어야합니다.

 

Auto Layout

일반적으로 스토리보드에서 constraint를 설정하면, 가장 가까운 뷰에 제약이 걸립니다.

가장 가까운 뷰가 여러 개라면, 안전 영역부터 제약이 걸립니다.

 

스토리보드에서의 스크롤뷰 구현

스토리보드에서 스크롤 뷰를 추가하고, 스크롤 뷰 아래에 서브뷰를 추가할 때 인터페이스 빌더는 오로지 컨텐츠 영역만 신경씁니다.

따라서, 

 

Intrinsic Size

컨텐츠의 크기에 맞게 사이즈를 조절합니다.

라벨의 경우 모든 텍스트가 들어가도록 사이즈를 할당해줍니다.

 

Static func vs Class func

둘 다 클래스 함수이며, 차이점은 static은 상속이 불가능한 반면 class는 상속을 받으며 또한 override할 수 있습니다.

final class func와 static은 동일한 기능을 수행하기도 합니다.