THIS IS ELLIE

WWDC2019 Architecting Your App For Multiple Windows 본문

공부/WWDC

WWDC2019 Architecting Your App For Multiple Windows

Ellie Kim 2020. 5. 15. 10:55

먼저 다중 window를 위한 앱 설계에 대해 이야기해 봅시다.

 

iOS 13에서 다중 window를 지원하는 것은 기존 앱을 더욱 유용하게 만들고

사용자의 생산성을 크게 향상하는 환상적인 방법입니다.

 

오늘 우리는 3가지 주요 주제를 다룰 것 입니다.

iOS 13의 다중 window를 사용할 수 있도록 하는 1) 앱 생명 주기 변경사항에 대해서 말하고

2) 새로운 UIScene delegate에 대해 자세히 살펴보고 어떤 종류의 작업을 수행해야 할지 이야기하고

마지막으로 3) ArchitectureKit의 좋은 사례를 살펴보고 너와 팀은 사용자에게 일관되고 완벽한 멀티태스킹 경험을 제공할 수 있도록 합니다.

 

Changes to app lifecycle

iOS 12 및 이전 버전에서 App Delegate의 역할과 책임에 대해 이야기하겠습니다.

App Delegate는 두 가지 주요 역할을 수행했습니다.

 

첫 번째는 애플리케이션의 프로세스 레벨 이벤트를 알려 줍니다.

(ex: App Launched, App Terminated)

 

두 번째는 애플리케이션의 UI 상태를 알려 줍니다.

이것은 iOS 12 그리고 이전 버전에는 완전히 문제 되는 것이 없습니다.

(ex: Entered Foreground, Became Active)

이 구조가 iOS 12 그리고 이전 버전 애플리케이션은 하나의 프로세스와 하나의 유저 인터페이스 인스턴스가 매치되었기 때문에 문제가 발생하지 않습니다.

 

변경된 App Delegate를 확인해보면 이전과 거의 비슷할 것입니다.

데이터베이스 연결하거나 데이터 구조를 초기화하는 것 등(one-time, non-UI)을 테스트해보면

iOS 12 및 이전 버전에서는 가능하지만 iOS 13 패턴에서는 유효하지 않습니다.

왜냐하면 애플리케이션은 여전히 하나의 프로세스만을 공유하지만,

여러 유저 인터페이스 인스턴스 또는 여러 scene sessions이 존재할 수 있기 때문입니다.

 

이는 App Delegate의 책임이 약간 변경되어야 함을 의미합니다.

 

App Delegate는 프로세스 이벤트 및 생명주기에는 여전히 책임이 있지만, 이제는 UI 생명주기와는 관련이 없습니다.

이제 UI 생명주기는 Scene Delegate가 처리합니다.

App Delegate에서 수행했던 UI 설정, 해제 작업은 이제 Scene Delegate의 방법으로 마이그레이션해야 합니다.

실제로 iOS 13에서 애플리케이션이 scene 생명주기를 채택하면,

UIKit은 UI 상태와 관련된 App Delegate 메서드 호출을 중지하고 새로운 Scene Delegate 메서드를 호출할 것입니다.

 

그리고 대부분 1:1 맵핑이 되기 때문에 매우 간단합니다.

(UIApplicationDelegate - UISceneDelegate)

걱정 마세요!

iOS 13에서 다중 window 지원을 채택하려는 경우 12 및 이전 버전에 대한 지원을 중단해야 한다는 것은 아닙니다.

다시 배포하는 경우 두 가지 방법을 모두 유지하면 UIKit은 런타임에 올바른 세트를 호출합니다.

 

App Delegate는 이제 UI 생명주기 역할은 하지 않지만 역할이 하나 더 추가됩니다.

 

새 scene session이 생성되거나, 존재하던 scene session이 삭제될 때 시스템이 App Delegate에게 알립니다.

작은 파란색 애플리케이션을 처음으로 시작해본다고 가정해봅시다.

그때 호출 스택을 살펴보겠습니다.

 

먼저, App Delegate가 didFinishLaunchingWithOptions를 호출하며, 이전과 동일하게 진행됩니다.

(데이터베이스 연결하거나 데이터 구조를 초기화하는 것과 같이 UI가 아닌 일회성인 작업을 말함)

바로 시스템에서 scene session을 만듭니다.

하지만 UIScene을 만들기 전 애플리케이션에 UISceneConfiguration을 요청합니다.

(UISceneConfiguration: UIKit이 특정 scene을 생성할 때 사용하는 객체와 스토리보드에 관한 정보를 담고 있음)

알맞은 configuration을 선택할 수 있도록 기회를 제공합니다.

(코드로 동적이게, info.plist에서 정적이게 scene configuration을 정의할 수 있음)

제공되는 파라미터를 잘 보고 context에 맞는 scene configuration을 골라야 합니다.

 

이제 우리 앱이 런치 되었습니다.

우리는 scene session을 가지고 있지만, 어떠한 UI를 볼 수 없습니다.

window을 구성하기 위해서는 사용자 활동(user activities), 상태 복원 활동(state restoration activities) 관련성을 체크해야 합니다.

 

window설정을 해주면 이제 앱이 보입니다.

그렇다면 사용자가 홈으로 돌아가려고 스와이프 하면 어떻게 될까요?

이전의 익숙한 방법(App Delegate에서의 호출)처럼 Scene Delegate의 willResignActive 그리고 didEnterBackground 메서드가 호출됩니다.

그러나 여기 흥미로운 것이 있습니다.

어느 시점 이후에 scene이 끊어질 수 있습니다.

scene이 background에 들어간 후, 시스템이 리소스들을 찾기 위해 메모리에서 해당 scene을 release 할 수 있습니다.

이렇게 되면 Scene Delegate가 메모리에서 해제되고 Scene Delegate가 보유한 모든 window계층 구조 또는 view계층 구조도 해제됩니다.

 

이는 다른 곳에서 보유한 메모리의 큰 자원을 deallocate 하고 release 할 수 있는 기회를 제공합니다.

(메모리 확보)

 

하지만, 사용자가 다시 돌아와 scene이 다시 연결될 수 있으므로,

사용자가 실제로 사용하는 데이터나 상태를 영구적으로 삭제하지 않도록 하는 것이 중요합니다.

사용자가 scene session을 실제로 스와이프 하고 명시적으로 파괴하려고 할 때 실제로 어떤 상황이 발생하는지에 대해 이야기해봅시다.

시스템은 App Delegate의 didDiscardSceneSessions를 호출할 것입니다.

이는 텍스트 편집 앱에서 저장되지 않은 텍스트와 같이 scene에 관련해 유저 상태나 데이터 인지 아닌지 delegate를 통해 확인할 기회를 줍니다.

 

실제로 앱 프로세스가 실행되고 있지 않는 동안 위로 스와이프를 해서 하나 이상의 UIScenes를 제거했을 수도 있습니다.

 

앱 프로세스가 실행 중이 아닌 경우 시스템은 폐기된 세션을 추적하고 다음에 애플리케이션이 런치 된 후에 이를 호출합니다.

Architecture

상태 복원에 대해서 이야기하겠습니다.

애플리케이션이 scene 기반 상태 복원을 구현하는 것이 중요합니다.

왜 그런지 살펴봅시다.

나는 문서 앱을 가지고 있고 여행을 계획하고 있으며, 지금은 4개의 다른 문서 세션이 열려 있습니다.

그러나 나는 packing list과 agenda에 정말로 집중하고 있습니다.

어느 시점에서, 시스템에 의해 이 다른 두 가지 road trip, attendees scene 연결이 끊기고 해제되었습니다.

만약 내가 여기서 상태 복원을 구현하지 않았으면, road trip으로 돌아갈 때 이전 상태로 돌아가지 않을 것입니다.

편집 중인 문서를 표시하지 않을 것입니다.

즉 새로운 window처럼 다시 시작해야 합니다.

이는 훌륭한 사용자 경험이 아닙니다.

우리는 어떻게 해결할 수 있을까요?

iOS 13에는 완전히 새로운 scene기반 상태 복원 API가 있습니다.

 

이것은 매우 간단합니다.

더 이상 view계층 구조를 인코딩하는 것이 아니라 다시 만들 window상태를 인코딩할 수 있습니다.

 

이것은 모두 NSUserActivity을 기반으로 합니다.

따라서 애플리케이션이 스포트라이트 검색 또는 핸드-오프 와 같은 강력한 기술을 활용하는 경우 동일한 활동을 사용하여 앱 상태를 인코딩 할 수 있습니다. iOS 13에서는 시스템에 되돌려주는 상태 복원 아카이브가 나머지 응용 프로그램의 동일한 데이터 보호 클래스와 일치한다는 점도 주목할 가치가 있습니다.

 

코드에서 이것은 어떻게 생겼습니까? 상태 복원을 구현하면 우리의 Scene Delegate는 현재 window에서 가장 활동적인(active한 userActivity) 사용자 활동을 호출할 것입니다.

그리고 그것을 리턴할 것입니다.

얼마 후 해당 scene 이 foreground로 다시 들어가 연결될 때 세션에 상태 복원 활동이 포함되어 있는지 확인합니다.

그렇다면 해당 activity를 사용합니다. 그렇지 않은 경우 새로운 window를 만들 수 있습니다.

즉, 사용자는 background에서 scene이 끊어졌는지 알지 못합니다.

 

마지막으로 다중 window를 지원할 때 발생할 수 있는 또 하나의 중요한 문제에 대해 이야기하겠습니다.

 

애플리케이션 scenes를 동기화하는 방법입니다. 좀 더 구체적으로 설명하겠습니다.

나는 채팅 앱에서 작업하고 있으며, 최근에 iOS 13에서 지원하는 다중 window를 추가했습니다.

 

그리고 몇 분 안에 무대에 참여할 친구인 Giovanni와 다른 뷰 컨트롤러에서 다른 scenes에서 같은 대화를 동시에 나누고 있음을 확인할 수 있습니다.

 

Giovanni에게 점심 준비가 되었다고 메시지를 보내주세요.

우리 scene 중 하나만 업데이트되었습니다. 왜 그럴까요?

글쎄, iOS에서는 많은 종류의 앱에서 뷰 컨트롤러가 이벤트를 수신하는 방식으로 구성되어 있음을 알 수 있습니다.

버튼 탭을 통해 전송 버튼을 누릅니다.

그런 다음 뷰 컨트롤러가 자체 UI를 업데이트합니다.

그런 다음 뷰 컨트롤러는 모델 또는 모델 컨트롤러에 알립니다.

이것은 하나의 사용자 인터페이스 인스턴스에 대해서만 괜찮습니다.

 

그러나 다른 scene에 동일한 데이터를 보여주는 두 번째 뷰 컨트롤러는 새로운 데이터로 자체 업데이트되도록 알림을 받는 것이 아닙니다. 이것이 문제입니다.

우리는 이것을 해결할 수 있습니다.

아키텍처 상, 이벤트를 수신하자마자 즉시 모델 컨트롤러에만 알리면 모델 컨트롤러가 실제로 관련 subscriber 또는 뷰 컨트롤러에게 새로운 데이터로 업데이트해야 한다고 알릴 수 있습니다.

우리가 이것을 할 수 있는 방법은 여러 가지가 있습니다.

delegate, notification 또 올해 출시된 Swift Combine프레임워크 등을 사용할 수 있습니다.

 

간단한 스위프트 예제를 살펴보겠습니다.

메시지를 보낼 때 return 버튼을 누르면 호출되는 현재 메서드가 있습니다.

메시지 모델 객체를 만듭니다. 뷰 컨트롤러가 자체 뷰를 업데이트합니다.

그런 다음 모델 컨트롤러를 유지하도록 알립니다.

가장 먼저 해야 할 일은 이 뷰 컨트롤러가 자체 뷰 상태를 변경하지 않아야 한다는 것입니다.

우리는 이 코드를 제거하고 나중에 다시 추가하겠습니다.

이제 해당 모델 컨트롤러의 add 메서드가 실제로 수행하는 작업을 살펴보겠습니다.

이것은 꽤 간단합니다. 우리가 하는 일은 그 새로운 메시지를 지속시키는 것입니다.

모델 컨트롤러가 다른 뷰 컨트롤러나 연결된 scene에 업데이트가 있다고 알릴 수 있기를 원합니다.

 

이 업데이트를 어떻게 보내시겠습니까?

이 이벤트를 강력하게 형식화하고 쉽게 디버깅하고 테스트할 수 있도록 이 이벤트를 패키지화하는 체계적인 방법을 원합니다.

연관된 값을 가진 스위프트 열거형입니다.

새로운 메시지 유형을 추가하겠습니다.

이것은(Message) 우리의 모델 컨트롤러가 새 메시지를 수신하여 생성한 다음 관련 뷰 컨트롤러 또는 scene으로 전송하는 객체입니다.

이것을 post 하고 싶기 때문에 NSNotificationCenter를 백업 저장소로 사용합니다.

subscriber에게 새로운 업데이트 이벤트를 post 할 메서드 한줄을 추가하겠습니다.

이제 우리의 모델 컨트롤러가 세 메시지가 추가되었다고 알려주면 우리는 그걸 유지한 후 새 이벤트와 post를 호출할 수 있습니다.

그런 다음 뷰 컨트롤러를 어떻게 변경해야 하는지 살펴보면 이 새로운 이벤트가 관찰(addObserver)됩니다.

이 경우 .NewMessageNotificationName이 이름입니다.

그런 다음 argument에서 알림을 받는 핸들러 메서드를 만듭니다.

업데이트 이벤트를 알림 객체로 전달하면 알림에서 해당 이벤트를 바로 가져올 수 있습니다.

그런 다음 이벤트의 종류를 쉽게 전환할 수 있으며, 관련 열거형을 만들었으므로 메시지를 꺼낼 수 있습니다.

 

이제 여기에서 사용자 인터페이스를 업데이트할 수 있습니다.

이 새로운 아키텍처를 구현한 후 동일한 메시지를 Giovanni에 보내면 어떻게 되는지 봅시다.

모든 scene이 업데이트됩니다.

 

전체적으로

우리는 App Delegate vs Scene Delegate의 차이점과 책임의 차이점에 대해 살펴보았습니다.

우리는 또한 몇 가지 주요 Scene Delegate 메서드들과 거기서 어떤 작업을 해야 하는지 살펴보았습니다.

또한 iOS 13에서 상태 복원이 중요한 이유와 새로운 scene 기반 API를 활용하는 방법에 대해서도 설명했습니다.

마지막으로, 단방향 데이터 흐름을 생성하기 위한 일부 고수준 패턴에 대해 이야기하여 모든 scene이 동일한 데이터를 공유하는 동안 동기화 상태를 유지할 수 있습니다.

 

resource: 

https://developer.apple.com/videos/play/wwdc2019/258/

 

Architecting Your App for Multiple Windows - WWDC 2019 - Videos - Apple Developer

Dive into the details about what it means to support multitasking in iOS 13. Understand how previous best practices fit together with new...

developer.apple.com

 

반응형

'공부 > WWDC' 카테고리의 다른 글

Apple 이벤트 2020  (0) 2020.09.23
WWDC2020 Become a Simulator Export  (0) 2020.08.12
WWDC2020 What's New in Swift  (0) 2020.06.30
WWDC2020 키노트 정리  (0) 2020.06.30
WWDC2019 LinkPresentation  (0) 2019.10.21