Overview
UIKit은 앱에 필요한 다양한 핵심적인 객체를 제공한다. 그 중에는 System과 상호 작용하는 객체, 앱의 main 이벤트 loop에서 동작하는 객체, 컨텐츠를 화면에 보여주는 객체가 포함되어있다. 개발자는 위 객체들 다수를 그냥 사용하거나 약간의 수정을 거쳐 사용할 수 있다. 어느 객체를 수정할 수 있으며 언제 객체들을 수정할 수 있는지 아는 것은 앱을 구현함에 있어서 중요한 요소이다.
UIKit app 의 구조는 Model-View-Controller (MVC) 디자인 패턴에 기반하고 있으며 위에서 언급된 객체들은 디자인 패턴에 맞춰서 목적에 알맞게 나뉘어지게 된다. 대표적으로 ViewController 와 app delegate 객체는 데이터 객체와 UIKit View 사이에서 데이터를 교환것을 조직해준다.
다음의 그림은 앱 객들의 핵심 구조를 나타낸 것이며 그중 UIApplication 객체는 앱의 main 이벤트 loop 를 구동시키고 앱의 전체적인 life cycle 을 관리해준다.
UIApplication
UIApplication 의 역할은 iOS 내부에서 동작하는 앱들을 위하여 컨트롤하고 협력할 수 있는 중앙화된 지점이다!
한걸음 더 들어가보기!
대다수의 iOS 앱은 오직 하나의 UIApplication 인스턴스를 갖고있다. 처음에 앱을 실행하면 시스템은 UIApplicationMain(_:_:_:_:) 함수를 호출한다. 앱이 다른 잡업을 처리하는 동안 위 함수는 shared 프로퍼티를 통해 singleton UIApplication 객체에 접근할 수 있도록 생성해준다.
앱의 application 객체의 주요 역할은 입력된 사용자 이벤트의 초기 routing 지점을 처리해주는 것이다. application 객체는 컨트롤 객체( UIControl 의 인스턴스)가 적절한 target 객체 앞으로 전달한 action 메시지를 전달해준다. application 객체는 현재 열려있는 윈도우 (UIWindow objects)의 목록을 관리해준다. 윈도우 목록은 앱의 UIView 객체를 회수하는데 사용할 수 있다.
UIApplication 클래스는 UIApplicationDelegate 프로토콜을 준수하는 delegate 를 정의하고 있으며 반드시 프로토콜의 메서드 중 일부를 구현해줘야 한다. application 객체는 runtime 에서 발생될 수 있는 중요한 정보를 delegate 에게 알린다. 예를 들어, app lauch, low-memory warning, app termination 의 runtime 상황이 있을 수 있다. 앱에 구현된 delegate 를 통해 적절하게 대응할 수 있도록 도와준다.
앱은 open(_:options:completionHandler:) 메서드를 통해 이메일 혹은 이미지 파일과 같은 resource 를 협력하면서 다룰 수 있다. 예를 들어, 앱이 이메일 주소와 함께 이 메서드를 호출하면 메일 앱이 실행된 후 메시지를 보여준다. 그 외에도 UIApplication 객체를 사용하면 device-specific한 행위에 대해 관리할 수 있다. 그 외에도 들어오는 터치 이벤트를 잠시 무시하거나 원격 notification 을 등록하거나 UI에서 실행, 실행 취소를 구현하는 등등 어려가지 메서드가 존재한다.
Main Run Loop
앱의 main run loop 는 사용자와 관련된 모든 이벤트를 처리해준다. UIApplication 객체는 앱이 시작될 때 main run loop 를 설정해주며 이벤트와 view 에 기반한 인터페이스를 처리하는데 활용된다. 이름이 말해주듯, main run loop 는 main 스레드에서 실행되며 사용자와 관련된 이벤트가 수신된 순서대로 처리될 수 있도록 보장해준다.
다음의 그림은 main run loop 의 구조에 대해서 보여주며 앱에서 어떻게 사용자의 액션에 결과물이 당신의 앱으로 전달되는지 보여준다. 사용자가 장치와 상호작용하는 동안, 이와 관련된 이벤트는 이벤트는 시스템에 의해 생성되며 UIKit 에 설정된 특정 포트를 통해 앱에 전달된다. 이벤트는 앱에 의해 내부적으로 큐에 담기며 main run loop 가 실행될 때마다 한번에 하나씩 앱에 전달된다. UIApplication 객체는 이벤트를 수신하고 어떤 작업이 수행되어야하는지에 관하여 판단해주는 첫번째 객체이다. 터치 이벤트는 보통 main window 객체로 전달되며 실제 터치가 이뤄진 View 로 전달된다. 다른 이벤트는 약간 다른 경로를 통해 앱 객체에 전달될 수 있다.
iOS 앱에 전달될 수 있는 이벤트는 다양하지만 가장 대표적으로 Touch 이벤트, Remote control Shake motion 이벤트, Accelerometer 같은 센서 이벤트, Location 이벤트, Redraw 이벤트를 생각해볼 수 있다. 이러한 이벤트의 일부는 앱의 main run loop 를 사용하여 전달된다. 물론 이 방식으로 전달되지 않는 이벤트도 존재한다. 일부 이벤트는 delegate 객체 혹은 개발자가 제공한 블록을 통해 전달될 수 있다. 자세한 정보는 iOS Event Handling Guide 문서에 나와있다.
touch와 remote control 과 같은 일부 이벤트는 앱의 respoder 객체에 의해 처리된다. Responder object 는 앱의 어디에서나 존재한다. (UIApplication 객체, view 객체, view controller 객체가 responder 객체의 예시이다. 대부분의 이벤트는 특정 responder 객체를 타겟으로 하지만 필요한 경우 responder chain 을 통해 다른 responder 객체에 전달될 수 있다. 예를 들어 어느 이벤트를 다루지 않는 view 가 그 이벤트를 받아서 자신의 superview나 view controller에 전달해줄 수 있다.
버튼과 같은 컨트롤 요소에서 발생한 터치 이벤트는 다른 타입의 view 에서 발생된 터치 이벤트와 다르게 처리된다. 컨트롤 요소에 대해서가능한 상호 작용의 수는 제한적으로 존재한다. 그래서 컨트롤 요소에서 발생한 상호작용은 액션 메시지로 다시 포장되어 적절한 target 객체로 전달된다. 이러한 방식의 target-action 디자인 패턴은 당신의 앱에서 사용자회된 코드를 손쉽게 실행시킬 수 있도록 도와준다.
Excution States for Apps
주어진 어느 순간에서 당신의 앱은 다음의 테이블에 언급된 상태 중 하나일 것이다. 시스템을 통해 발생한 액션에 응답하기 위해 시스템은 당신의 앱의 상태를 변환시킨다. 예를 들어 사용자가 홈 버튼을 클릭하거나 전화가 오거나 이와 비슷한 interuption 이 발생하면 현재 실행중인 앱은 interruption에 응답하여 앱의 현재 상태를 변화시킨다.
State (상태) | Description (개요) |
Not running | 앱이 현재까지 실행되지 않았거나 실행되었으나 시스템에 의해서 종료된 상태이다. |
Inactive | 앱이 foreground 에서 실행 중이지만 현재 이벤트를 수신하고 있지 않다. (그럼에도 다른 코드를 실행할 수 있을 것이다.) 앱은 보통 다른 상태로 전환하려고 이 상태에서 잠시동안 머문다. |
Active | 앱이 foreground 에서 실행중이며 이벤트를 수신하고 있다. 이것이 foreground 앱의 일반적인 모드이다. |
Background | 앱이 background 에 있으며 코드를 실행하고 있다. 대다수의 앱은 이 상태에 suspend 되는 과정에서 잠시동안 들어가있다. 그러나 추가적인 실행 시간을 요청한 앱은 일정 시간동안 이 상태에 남아있을 것이다. 추가적으로, background 로 직접 실행된 앱은 inactive 상태 대신에 background 상태로 진입한다. |
Suspended | 앱이 background 상태이지만 코드를 실행시키고 있지 않는다. 시스템은 앱을 자동으로 이 상태로 옮겨주며 그 전에 앱에게 먼저 알려주지 않는다. suspended 동안 앱은 메모리에 남아있지만 코드를 실행하지 않는다. 메모리 부족 상태가 발생할 때, 시스템은 foreground 앱의 공간을 확보하기 위해 suspended 앱에게 말하지 않고 종료시킬 것이다. |
대부분의 상태 전환은 상응하는 앱의 app delegate 객체의 메서드를 호출하며 함께 동작한다. 다음의 메서드들은 앱의 상태가 변화할 때 적절한 방식으로 응답할 수 있도록 한다.
- application:willFinishLaunchingWithOptions : 앱이 launch 될 때 첫번째로 실행되는 코드입니다.
- application:didFinishLaunchingWithOptions : 앱이 사용자에게 보여지기 전에 마지막 initialization 작업을 수행할 수 있도록 도와줍니다.
- applicationDidBecomeActive : 앱에게 foreground 앱이 된다는 점을 알려줍니다. 단시간에 준비해야하는 것에 대해 이 메서드를 사용합니다.
- applicationWillResignActive : 앱이 foreground 앱에서 벗어나는 것을 알려줍니다. 앱이 비활성화 상태로 들어가기위해 사용합니다.
- applicationDidEnterBackground : 앱이 background 에서 실행중이며 어느 때나 종료될 수 있는 상태이다.
- applicationWillEnterForeground : 앱이 backgorund 에서 foreground 로 전환되는 점을 알려준다. 하지만 여전히 active 상태는 아니다.
- applicationWillTerminate: 앱이 종료될 것이라고 알려준가. 이 메서드는 앱이 suspended 되었을 때 호출되지 않는다.
Reference
' Apple > iOS Dev Challenges' 카테고리의 다른 글
[Challenge] GCD (0) | 2021.12.17 |
---|---|
[Challenge] 간단한 네트워크 통신에 대해 탐구해보자! (0) | 2021.12.16 |
[Challenge] 화면 전환에 대해 탐구해보자! (0) | 2021.12.15 |
[Challenge] iOS 13 이후의 Scene 톱아보기! (0) | 2021.11.25 |
[iOS - Laboratory] iOS 앱의 Life Cycle 추적해보기 (iOS 12와 이전 버전) (0) | 2021.11.25 |