본문 바로가기

UIKit

[UIKit] UIKit 앱실행부터 UIView까지(iOS 13 ⬆)

 

안녕하세요 주니오스입니다✋

 

 

한동안 프로젝트에 참여하느라 블로그글을 자주못썼습니다.😓

 

 

SwiftUI 프로젝트를 진행하던 도중 UIKit 프레임워크를 사용해하는 경우가 생각보다 많았습니다.

 

 

UIKit공부에 중요성을 느끼게 되어 해당 프레임워크의 앱 실행 플로우에 대한 포스팅을 진행하게 되었습니다.

 

 

공식적으로 제공하는 구조는 아래와 같습니다.

앱 구조

 

 

UIApplication

 

각각의 앱은 하나의 어플리케이션 객체를 가집니다.

 

앱을 실행하면 가장먼저 UIApplication인스턴스가 싱글톤 패턴으로 생성됩니다. 

 

shared 전역 프로퍼티를 통해서 접근할 수 있습니다.

 

앱에 발생하는 모든 이벤트는 어플리케이션 인스턴스를 거쳐 적절한 UIWindow에 전달됩니다.

 

iOS 13이상 부터는 AppDelegate를 통해서 Scene의 생성과 종료를 다루게 됩니다.

 

iOS 13이전에는 앱의 전반적인 상태변화에도 관여하였지만 해당기능은 Scene에서 담당하게 되었습니다.

 

그 이유는 iPad에서 같은 앱이지만 여러가지 화면을 가질 수 있는 기능 때문입니다.

 

각각의 화면은 Scene이라는 독립적인 객체 구분됩니다.

 

앱실행시 생성될 Scene의 정보를 담은 UISceneConfiguration인스턴스를 반환하는 AppDelegate매서드 입니다.

func application(
	_ application: UIApplication, 
    configurationForConnecting connectingSceneSession: UISceneSession, 
    options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

 

UISceneConfiguration는 아래 3가지 정보를 담고 있습니다.

 

UISceneConfiguration

 

3가지 정보를 바탕으로 Scene은 형성되며 해당 정보들이 어떻게 사용되는 지에 대해서는 후에 설명하겠습니다.🤔

 

 

UISceneDelegate(UIWindowSceneDelegate)

 

UIWindowSceneDelegate는 UIWindowScene을 관리하는 프로토콜입니다.

 

 

UIWindowSceneDelegate를 직접 생성할 필요없이

앞서 언급한 UISceneConfiguration의 정보를 사용하여 시스템이 자동 생성합니다.

 

 

UISceneDelegate는 해당 타입의 부모 프로토콜로 Scene의 상태변화와 관련 매서드를 요구합니다. (다음 포스팅에서 다루겠습니다.)

 

 

UIWindowSceneDelegate는 추가로 window 프로퍼티를 요구하며 해당 프로퍼티를 사용하여 앱실행시 앱의 UI를 표시합니다.

 

 

window프로퍼티는 UIWindow타입으로 UIView의 하위 클래스입니다.

 

 

윈도우는 앱이 UI를 표시하기 위한 가장 하위계층을 나타내며 모든 UI는 윈도우 위에 존재하게 됩니다.

 

 

UIWindow인스턴스를 RootViewController즉 윈도우 위에 표시할 최초 ViewController인스턴스를 가집니다.

 

 

여기까지 읽으셨다면 아래구조로 화면이 표시됨을 이해하실 수 있습니다.

Basic Flow

 

Xcode를 사용하여 UIKit 프로젝트를 생성하는 경우 위 과정이 자동으로 구현됩니다.

(그래서 별도의 설정 없이도 바로 UIView구현을 할 수 있었습니다.)

 

 

자동화된 기능이 어떻게 동작하는지 하나하나 확인해 보겠습니다.🤗

 

 

앞서언급한 UISceneConfiguration부분을 다시한번 살펴보겠습니다.

 

 

UISceneConfiguration

 

공식문서에는 다음과 같이 나와있습니다.

 

 

UISceneConfiguration이 스토리보드를 가지는 경우 UISceneDelegate의 UIWindow가 자동으로 할당된다.

 

 

따라서 UIWindow를 생성하지 않아도 화면 표시에 문제가없던 것이였습니다.

 

 

func scene(
	_ scene: UIScene, 
    willConnectTo session: UISceneSession, 
    options connectionOptions: UIScene.ConnectionOptions) {
	
    // 앱과 Scene이 연결되기 전 불리는 코드로 window값을 할당하는 코드가 따로없다
    
    guard let windowScene = (scene as? UIWindowScene) else { return }

}

 

 

다이어 그램으로 본다면 구조는 아래와 같습니다.

UISceneConfiguration정보 전달

 

 

UISceneConfiguration 인스턴스에 대한 정보는 InfoPlist에서 지정할 수 있습니다.

 

Info.plist에 정의된 UISceneConfiguration

 

※ info.plist에 $와 함께 사용되는 환경변수는 아래 명령어로 쉘에서 확인할 수 있습니다.

더보기
xcodebuild -project [프로젝트명].xcodeproj -target [프로젝트내 타겟이름] -showBuildSettings

 

info.plist에 작성한 정보는 UISceneConfiguration이니셜라이저에 의해 이름으로 불로올 수 있습니다.

 

 

해당 인스턴스를 AppDelegate의 매서드가 반환함으로써 Scene에 사용되게 되는 구조입니다!😎

 

 

func application(
	_ application: UIApplication, 
    configurationForConnecting connectingSceneSession: UISceneSession, 
    options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    
    // info.plist에 저장된 이름으로 불러옵니다!
    return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

 

 

두개이상의 윈도우를 가지는 Scene

 

앞서 제시한 사진을 다시한번 보겠습니다.

 

앱 구조

 

하나의 Scene에는 다수의 Window가 존재할 수 있는 것처럼 보입니다.

 

 

실제로 UIWindowScene은 windows라는 프로퍼티를 가지며 타입은 UIWindow배열입니다.

 

 

해당 배열은 get-only로 배열 포함되려면 UIWindow생성자에 Scene객체를 매개변수로 전달해야 합니다.

 

guard let windowScene = (scene as? UIWindowScene) else { return }
let newWindow = UIWindow(windowScene: windowScene)

 

 

WindowScene을 전달하지 않고도 윈도우를 생성할 수 있지만 그렇게 생성한 윈도우는 화면상에 표시되지 않습니다.

 

 

UIWindow는 UIScreen을 통해 현재디바이스의 스크린에 대한 정보를 얻고 전체영역을 차지합니다.

 

 

따라서 다수의 window가 있어도 결국화면상에 표시되는 윈도우는 하나입니다.

 

 

윈도우 인스턴스의 makeKeyAndVisible매서드를 호출하여 특정 윈도우를 화면상에 표시할 수 있습니다.

 

newWindow.makeKeyAndVisible()

 

 

KeyWindow

화면 터치와 같이 좌표값과 관련된 이벤트의 경우 현재 보이는 윈도우에 해당 이벤트가 전달됩니다.

 

하지만 키보드입력과 같이 좌표에 관련하지 않은 이벤트의 경우 현재 Scene의 KeyWindow에게 해당 이벤트가 전송됩니다.

 

UIWindow는 isKeyWindow프러퍼티를 통해서 현재 인스턴스가 속한 Scene에서

자신이 키 윈도우인지 아닌지  여부를 확인할 수 있습니다.

 

makeKeyAndVisible매서드는 윈도우를 화면에 표심함과 동시에 키윈도우로 만듬으로

 

사실상 현재화면이 키윈도우라고 볼 수 있을 것 같습니다. 🤔

 

 

 

정리

지금까지 정리한 내용을 다이어그램을 표시하면 다음과 같습니다.

 

최종 정리 다이어 그램

 

 

본격적인 UIKit공부에 앞서 기본적으로 UIKit이 UI를 어떤 과정을 거쳐 표시하는 지 알아보았습니다.

 

 

앞으로 다룰 포스팅과 관련해 반드시 다뤄여하는 개념이라고 생각합니다!

 

 

다음 포스팅으로는 Scene상태와 ViewController의 상태관리를 함께 다뤄 Scene에 ViewController로 자연스럽게 동작이 전이되는 방법을 포스팅 해보겠습니다!

 

 

틀린 부분에 대한 지적은 언제나환영입니다! 감사합니다! :D