티스토리 뷰

반응형


안녕하세요 :) Zedd입니다.

다들 추석연휴 잘 보내시고 계신가요????!

벌써 토요일이라니..오늘 목표는 Scene을 좀 이해하는 게 목표입니다..

꼭 공부해보고싶었던 SceneDelegate의 존재(?)의 이유...


항상 iOS, Swift ) 이런식으로 붙히는 편인데..이번건 좀 애매하네용...!!

iOS는 아니자나..그럼 iPadOS ) 라고 해야하나..? 

카테고리 하나 또 만들어야하나.......???

iPadOS가 맞을까요?


+ ) 아 다쓰고 다시 왔는데..이 글의 제목이 SceneDelegate인게 맞는걸까 하는 의문이 드네요.....

흐음

Architecting Your App for Multiple Windows가 맞는걸까? 




일단 걍 씀


아 그전에 또 노래 추천...

ㅎㅎ

Cashmere Cat의 FOR YOUR EYES ONLY입니다..!

일주일 전에 나온 곡!!

뭔가 san holo느낌나서ㅠㅠㅠㅠ 좋음..




SceneDelegate.swift...이자식...



Xcode 11로 iOS 프로젝트를 만들면 AppDelegate는 알겠는데.. 

SceneDelegate라는 녀석이 있는 것을 볼 수 있습니다.


갑자기 SceneDelegate.swift는 왜생겼냐???

그것은..iPad에서 multi window를 지원하기 때문이죠..


따흐흑


iOS 13이상에서 사용자는 앱 UI의 여러 인스턴스를 동시에 만들고 관리할 수 있으며, 

app switcher를 사용하여 서로 전환 할 수 있게 되었죠.

UI의 각 인스턴스는 다른 컨텐츠를 표시하거나, 동일한 컨텐츠를 다른 방식으로 표시합니다. 

위 그림을 예로 들면, 사용자는 특정 요일을 표시하는 캘린더, 한달 전체를 표시하는 캘린더 등을 표시할 수 있게되죠.


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

WWDC19의 Architecting Your App for Multiple Windows세션을 먼저 봐야 할 것 같아요 일단 :ㅇ

15분 밖에 안되니까!!! 꼮 보세요!!!!





한번 짧게 요약이 될지는 모르곘지맘ㄴ 해보겠습니다.



iOS 12를 포함한 그 이전에서는 App Delegate의 역할이 뭐였죠?

크게 2가지 역할이 있었는데요.



하나는 process Lifecycle. 

니 프로세스,, 그니까 앱이겠죠? 니 프로세스가 Launch되고, terminate됐는지 알 수 있었죠. 

그리고 2번째로 UI Lifecycle이라고 했는데, UI의 State를 알 수 있었습니다.



뭐 이런 메소드를 통해서요.

이까지는 ㅇㅋ?


지금 이거는 iOS12를 포함한 이전까지는 완-벽하게 괜찮죠

왜냐? 

앱은 오직 "하나의 프로세스"와 그에 맞는 "하나의 UI"만 가지기 때문이에요.


하지만 iOS 13부터는 아닙니다!



앱은 여전히 하나의 프로세스만을 공유하지만, 

여러 UI 인스턴스 또는 Scene session이 있을 수 있기 때문이죠.

이는 App Delegate의 책임(or 역할)이 약간 변경되어야 함을 의미하죠. 

왜냐?????


프로세스 이벤트 및 Lifecycle에는 여전히 AppDelegate가 책임을 가지지만 

더이상 UI Lifecycle과는 관련된것이 없기때문입니다.



바로 이렇게요.


그럼 UI Lifecycle은 누가 햄



그~~~걸 SceneDelegate가 해냅니다


UI state와 관련된 것들을 이제는 SceneDelegate가 처리한다는 뜻입니다. 

즉...내가 AppDelegate에서 했던... UI setup / teardown 작업들을.. 

SceneDelegate로 마이그레이션 해야한다는 뜻ㄹ임ㅋㅎ 



iOS 13에서 앱이 new scene lifecycle을 "채택"(adopts)하면, 

UIKit은 AppDelegate에 있는 UI state와 관련된 메소드 호출을 중지합니다.

대신 SceneDelegate에 있는 메소드들 호출 해준다구 함 


궁금한게 multi window지원을 안할 순 없나?...



대부분의 경우 1:1로 매칭되는 메소드가  SceneDelegate에 있으니 암튼 하면 댐



iOS 13에서 multiple windows support를 채택하려는 경우, iOS12 및 이전버전에 대한 지원을 "중단"해야한다는 의미는 아님. 


"you can simply keep both sets of these methods and UIKit will call the correct set at runtime."

both sets이라 함은 원래의 AppDelegate랑 SceneDelegate + 새로운 AppDelegate..말하는듯(?) 

암튼 그 2개의 세트를 유지하면 UIKit은 런타임에 올바른 set을 호출한다고 하는 것 같습니다.


제 번역이 틀렸을 수도 있습니다...?!


자 암튼

지금 우리가 본 변경된 AppDelegate가 가지는 책임말고도 AppDelegate가 가지는 또 다른 책임이 있는데요



Session Lifecycle입니다.

이제 새로운 Scene Session이 생성되거나, 기존 Scene Session이 삭제될 때 시스템이 AppDelegate에게 알리게 됩니다.


자 이제 call stack을 좀 더 자세히 살펴볼게욘



파란색앱 눌르면 어케댐


AppDelegate가 didFinishLaunchingWithOptions~을 호출합니다. 똑같네요 이건 

이곳에서 UI가 아닌 일회성 설정을 하는게 좋다고 합니다.


그런 다음 바로, 시스템에서 Scene Session을 만듭니다

하지만 "실제 UI Scene"이 만들어지기 전에, 앱은 UIScene configuration을 요청해야합니다.




이 configuration은 scene delegate, 스토리보드 및 scene을 생성할 scene subclass를 지정합니다. 

(This configuration specifies what scene delegate, what story board, and if you specified, what scene subclass you want to create the scene with.)


이러한 scene configurations은 코드에서 동적으로(dynamically) 정의하거나, info.plist에서 정적으로(statically) 정의할 수 있습니다.


또한 올바른 configuration을 선택할 수도 있습니다. 

main scene configuation이 있을수도 있고, accessory scene configration이 있을 수 있잖아요? 

따라서 저 메소드에 제공된 옵션 파라미터를 context로 사용하여 올바른 scene configuration을 선택해야합니다. 


info.plist에서 이러한 항목을 정의하면 굉장히 간단하다구 합니다.



저기 파라미터에 name보이죠.

name만 참고하면 들어오는 sessionRole의 role을 전달해야합니다.

이;게 먼소리야;;


자 암튼 이제 

우리의 앱이 launch되었습니다.


자 아까 시스템에서 Scene Session을 만들었다고 했죠? 

하지만 우리는 아직 UI를 볼 수 없습니다.



UI가 아직 안뜬거 보이죱...!

따흑



암튼 이때, 우리의 scene delegates가 (아까 만들어진) 들어온 scene session에 연결된다구해요.


암튼 여기서..!!! 어떤일을 해야하는지 알아보도록 합시다.



여기서  새로운 UI Window initializer(new designated UI window initializer)를 사용하여 UI Window를 설정 할 수 있습니다.



여기서 중요한 점은 여기서 window을 구성 할 

관련 user activities 또는 state restoration activities도 확인해야합니다.

이부분에 관해서는 이따가 더 자세히 나와욥



자;;이까지 다 하고 나면



드뎌 앱이 보임;;;;


자 이상태에서 홈으로 가보겠습니다.



이러케


그러면



익숙한 메소드들(will resign active, did enter background )이 호출되게 됩니다.

물론 Scene Delegate에서요.


그럼 이제 어떤 일이 일어나냐면.

시간이 지나면, 우리의 scene 연결이 끊어질(disconnected) 수 있습니다. 



이게 먼말이얌



리소스를 회수하기위해, scene이 background에 진입 한 후 어느 시점에 해당 scene을 메모리에서 해제 할 수 있습니다. 

(in order to reclaim resources, the system may at some point after your scene enters the background, release that scene from memory.)


즉, 우리의 scene delegate가 메모리에서 해제되고, scene delegate가 보유한 window hierarchies 또는 view hierarchies가 해제됩니다.

그러나 scene이 나중에 다시 연결(reconnect)될 수 있으므로 사용자 데이터나 상태를 영구적으로 삭제하지 않는 것이 중요합니다.


scene이 다시 돌아올 가능성은 있지만 scene을 메모리에서 해제한다..? 잘 이해가 안가네 그럼 다시 돌아가면 그때 다시 만드나?..


자 그럼 


사용자가 "명시적으로" 앱을 종료시켰을 때 어떤일이 일어나는지 보도록 합시다.




시스템은 AppDelegatedidDiscardSceneSessions을 호출합니다.

이렇게 하면..



뭐 저장되지 않은 텍스트 편집 초안이라던가...scene과 관련된 모든 user data  또는 상태를 영구적으로 삭제됩니다.


아 ㅇ;거 뭔소리지??

"Now, it's also possible that one of your users removed one or more UIScenes from the switcher by swiping up while your actual app process was not running.

If your process was not running, the system will keep track of the discarded sessions and call this shortly after your application's next launch."


음..그러니까./...앱 프로세스가 "실제로" 실행되지 않는 동안, switcher(그 앱 스위처 말하는거겠죠?) 에서 하나이상의 UIScenes을 제거 했을 수도 있씁니다.

프로세스가 실행중이 아닌경우, 시스템은 discarded sessions을 계속 추적하고, 앱이 다음에 실행된 직후에 이를 호출합니다.


엥./..

음 그러니까 didDiscardSceneSessions이 다음 앱 launch때 다시 호출될 수 있다...라는 말이죠?



어흑 잘 이해가 안가...이게 왜 다음 launch이후에 왜 실행돼..?

네 잘 모르겠습니다!!!!!!! 네 그렇습니다..아는 분 알려주세욘


자 이제 



에 대해 이야기 해본다구 합니다


첫번째. state restoration

자..제가 state restoration를 잘 몰라서..일단 한번 보겠습ㄴ다.


자 일단!!!! iOS 13에서 state restoration은 더이상 멋지지(?) 않습니다. 

(In iOS 13, state restoration is no longer a nicety.)

앱에서 scene-based state restoration을 구현하는것이 중요합니다.


자 왜그런지 볼까요? 



~ app switcher ~

document app이구요. 여행을 계획중이고, 4개의 서로 다른 세션의 문서가 열려있네요.



근데 나는 packing list랑 agenda에 포커싱하고있다고 쳐보겠삼

그럼 어느 순간....



Road trip이랑 attendees 세션이........... 시스템에 의해ㅔ disconnect되고 release됩니다...


자!! 여기서 제가 state restoration를 구현하지 않았다면....다시 Road Trip으로 돌아갔을 때 그 전에 내가 뭐 편집하고 있던 문서로 돌아가지 않을거에요.

그냥 새로 시작하는 것 처럼.. brand-new window인 것 처럼..시작하게 되고.. 

이건 좋은 UX가 아니죠?


어케 해결하는 부분?



iOS 13은 새로운 scene-based state restoration API를 가지고 있습니다..!!!!!!!

아주 간-단하다고 해요..?


원래 state restoration하려면 view hierarchies를 encoding했나봐요..? 

근데 이제는 더이상 view hierarchies를 encoding하는게 아니라

state를 encoding하여 window을 다시 만들 수(recreate) 있습니다. 


이것은 모두 NSUserActivity를 기반으로 한다고 해요.

따라서 앱이 spotlight search나 handoff와 같은 기술을 활용하는 경우, 동일한 activities를 사용하여 앱 state를 encoding할 수 있습니다......흠..


그리고 iOS 13에서는 시스템에 반환하는 state restoration archive가 나머지 앱과 동일한 데이터 보호 클래스와 일치하는 점...

도 주목할만 하다고 하는데 이게 왜ㅑ지?????

아니 제가 state restoration에 대해서 잘 몰라서 뭔가 전달이.........잘 안되네요. 

Data protection클래스를 사용해가지구 안전하다는건가?...



암튼 코드를 보죠



SceneDelegate에서 scene에 대한 state restoration을 구현 한 다음에, 

현재 window에서 가장 active한(?) 관련 user activity를 찾는 메소드를 호출합니다.

그리고 그걸 return함..

아 씨

먼소리야 진짜


아...


저는 이게 원래 제공되는 메소든줄 알고..아니 왜 없어 했는데

그냥 현재 user activity를 가져온다는 그냥...custom 메소드였군요...

글쿠나...


암튼..


이제 다시 앱이 foreground로 들어와서 다시 연결될때(그래서 willConnetcTo인듯), 

세션에 state restoration activity가 있는지 확인합니다. 있으면 해당 activity쓰는거고 ㅇㅇ 없으면 brand-new window 다시 만드는거고 ㅇㅇ


그리고 마지막 2번째. 

가장 관심이 많을 것 같은데...



씬 동기화...



똑같은 화면...

메세지 보내보겠삼




자 메세지를 보냈더니 메세지를 보낸 그 viewController의 view만 업데이트가 되었죠.



대부분 ViewController가 이벤트를 수신하는 방식으로 구성되어있습니다.

버튼이 탭되면, viewController가 자기 자신을 업데이트 하고, 

그런 다음에 viewController는 model 또는 modelController에 알립니다.




보통 이거는 하나의 UI인스턴스에서는 괜찮죠.........


하지만 이제는 동일한 데이터를 보여주는 새로운 viewController가 있자나요 

이 새로운 viewController는 새 데이터로 자신을 업데이트 하라는 알림을 받을 수 없습니다.

이게 문제임;;;


그렇다면 이걸 해결 할 방법은..



버튼 탭을 받은 viewController가 이벤트를 수신한 즉시 modelController에게 통보하고




 modelController가 실제로 관련된 subscribers에게 이를 통지하거나 

viewController에게 새로운 데이터로 업데이트 해야한다고 알려주면 되겠죠.


코드를 한번 볼까요. 원래 한쪽 viewController만 업데이트 되던 코드입니다. 



아까 본 것과 똑같이. 일단 자기가 가지고 있는 view를 업데이트를 한 후에!!! model을 업데이트 합니다. 


일단 그럼 가장 먼저 해야 할 일은;; 

viewController가 자신의 view state를 변경하지 않아야 한다는 거죠.

(view controller should not be mutating its own view state.)



바로 이렇게 말이죠. 아까 본 것 처럼 바로 모델을 업데이트 하는거죠.

그럼 add메소드를 봐봅시다.



ㅇㅇ

지금은 모델이 그 관련된 viewController들(?)에게 업데이트 하라고 알리는 부분이 아직 안나왔네요.



이부분은 자세히 설명 안할게요. 동영상 보셈



암튼 add메소드가 이렇게 변함

그럼 notification을 post했으니.....이 notification을 관찰하는 옵저버를 등록해야겠죠? ViewController에?



ㅇㅇ그러하다


암튼 이렇게 하면....



화질구지.......

아니 키노트에 둘다 업데이트된 사진이 없어서..동영상 캡쳐함


자ㅣ 암튼 제가 궁금했던 부분만 딱 알려줘서 아주 훌륭한 세션.....이라고 생각되네요 :D

뭐 다른 모든 앱이 똑같이 대응은 해야겠지만...예제로 든 채팅앱같은 경우에는 특히나..........

화이팅...!!!!



오늘이 벌써 토요일인게 믿기지가 않는데............................

남은 연휴 잘 보내세용~.~







반응형