SwiftUI

WidgetKit (2) - TimelineEntry / TimelineProvider / TimelineReloadPolicy

Zedd0202 2020. 8. 9. 15:23
반응형

 

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

 여기 있는 글들을 꼭 읽고 와주세요. 

 

오늘은 TimelineEntry와 TimelineProvider에 대해서 공부해보겠습니다. 

이러한 친구가 만들어져있을텐데요.

이 SimpleEntry가 TimelineEntry타입을 채택하고 있는 것을 보실 수 있습니다.

TimelineEntry에 대해 먼저 알아볼텐데요.

 

그 전에 먼저!!!! WidgetKit의 작동방식을 먼저 살펴보겠습니다. 

자 저희가 이제 홈 화면에 가서 Widget을 볼거에요.

 

 

ㅋ,,.,

위젯보는데

응 로딩 기다려야돼~

는 좀 오바란 말이에요?!

애플에 말에 의하면 평범한 사람은 하루에 90번 이상 홈 화면을 보지만,

그 중 몇 분만 홈화면에서 머무른다고 해요.

근데 그 짧은 머무르는 시간에도 로딩을 기다려야하는건 좀 ㅂㄹ

 

아무튼 이 Widget이 바로바로 떴으면 좋겠다 이거에요. 

그래서 애플은 이 Widget이 바로바로 뜰 수 있도록!!!!!!!!!! 구현을 했어요.

 

위젯이 항상 정적인 내용을 보여주는게 아니죠? 뭔가 내가 볼 때 마다 업데이트가 되어있어야 할거에요.

위 그림이 WidgetKit의 작동방식인데요.

내가 위젯을 업데이트 할 Date를 WidgetKit한테 줘야해요

제가 이때 이때 Widget을 업데이트해!! 라는 시간을 담은 배열을 넘겨주면

WidgetKit은 그걸 보고 그 시간이 되면 그 때 나와야 할 view를 Widget에 전송한다고 해요.

 

그러니까 "이미" view가 준비되어있는거에요.

view를 패키징 해놓고

WidgetKit : 어 지금 Widget업데이트 할 시간이야?

지금 시간에 나가야할 view가 너구나? 너 나가

가 되는거에요. 그래서 바로 볼 수 있는거에요.

 

그럼 일단 우리가 알아야 할건 모다!?!?

 아 위젯을 만들려면 Widget을 언제 업데이트 할지, 즉 Date를 담은 배열을 줘야하는구나

이걸 WidgetKit에서는 Timeline이라고 합니다.

즉 WidgetKit에게 Timeline을 줘야합니다.

아직 잘 모르지만 Provider의 getTimeline메소드를 보겠습니다.

하단에

이런 코드가 있죠? 

Timeline을 만들어서 completion으로 넘기는 것을 볼 수 있습니다.

넘겨주는 entries는 [TimelineEntry] 타입입니다. 

 

TimelineEntry


TimelineEntry는 프로토콜입니다.

정의는 굳이 말해봐야 더 헷갈리니 적진 않을게요.

TimelineEntry은 프로토콜이니 뭔가 필수적으로 요구하는 프로퍼티나 메소드가 있을 수 있겠죠.

date라는 프로퍼티를 필수적으로 요구합니다.

이 date는 위에서 언급한!!! WidgetKit이 widget을 rendering할 date를 의미합니다. 

 

필수적으로 구현해야하는 프로퍼티가 date라면 optional하게 받는 프로퍼티가 있습니다.

구현해줘도 되고, 안해줘도 됩니다. 

relevance. Widget 컨텐츠와 사용자의 관련성을 의미하는 프로퍼티입니다. 

 

date는 이제 아시겠죠? 

근데 relevance는 뭔가 아직 감이 안오네요🤔

relevance는 TimelineEntryRelevance타입인데요. 

이 친구는 현재 및 과거 타임라인의 다른 항목과 비교하여,

타임 라인 항목의 상대적 중요성을 나타내는 객체라고 합니다. 

이 글에서 smart stack에 관한 이야기를 했었죠? 그것과 관련된 친구입니다.

WidgetKit은 현재 점수(score)에 따라 특정 위젯을 맨 위로 올려주는..그런 매커니즘을 가지고 있는 것 같아요. 

아무튼 이 친구는 optional이라 꼭 구현하지 않아도 됩니다.

 

 

Timeline과 TimelineEntry에 대해서 조금 감이 오시나요!? 그럼 TimelineProvider를 알아보겠습니다. 

 

 

TimelineProvider


TimelineProvider 역시 프로토콜입니다. 

TimelineProvider는 Provider라는 타입이 채택하고 있는 걸 볼 수 있습니다.

TimelineProvider는 Widget의 디스플레이를 업데이트 할 시기를 WidgetKit에 알려주는 타입이라고 해요.

 

WidgetKit은 다양한 시간(?)에 Provider에게 Timeline을 요청한다고해요.

 

WidgetKit : 야 타임라인 줘봐

Provider : 넵..!! 

 

WidgetKit 부장님은..까다로워가지고...요청 할 때 2가지 방법 중 하나로 타임라인을 요청합니다.

1. WidgetKit : Widget 현재 상태 나타내는 스냅샷 줘봐 (정확히는 single immediate snapshot)

2. WidgetKit : 현재 상태 및 Widget상태가 변경 될 미래 날짜가 포함된 타임라인 엔트리 배열 줘봐

 

 

Widget현재 상태 나타내는 스냅샷 줘봐


 

자..사용자가 위젯을 추가할 때를 생각해봅시다.

저기 Widget View가 "이미" 보이잖아요!? 

저건 도대체 어디서 가져오는 거란 말임;;;

WidgetKit은 이런 위젯을 추가할 때와 같이 일시적인 상황에서 위젯을 표시하기 위해서 Snapshot 요청을 합니다.

네! 이 메소드가 불리게 되어요.

파라미터로 context가 있는 것을 보실 수 있는데요.

이따가 나올 timeline메소드에서도 이 context가 파라미터로 있답니다.

이 친구의 타입은

TimelineProviderContext라는 struct입니다. 이 친구를 중간에 설명하면 좀 흐름이 끊길 것 같아

따로 글을 썼어요. 참고해주세요.zeddios.tistory.com/1091

 

WidgetKit - TimelineProviderContext

안녕하세요 :) Zedd입니다. WidgetKit글을 쓰다가...TimelineProviderContext만 정리해보면 좋을 것 같아 정리합니다. TimelineProviderContext 이 TimelineProviderContext는 Widget이 렌더링되는 방법에 대한..

zeddios.tistory.com

 

1. WidgetKit : Widget현재 상태 나타내는 스냅샷 줘봐 (정확히는 single immediate snapshot)

는 이제 알겠고..

2. WidgetKit : 현재 상태 및 Widget상태가 변경 될 미래 날짜가 포함된 타임라인 엔트리 배열 줘봐

이제 이걸 공부해볼게요.

 

현재 상태 및 Widget상태가 변경 될 미래 날짜가 포함된 타임라인 엔트리 배열 줘봐


사용자가 이제 Widget을 추가했어요!!! 

추가하면 WidgetKit은 Widget을 추가 한 후, timeline요청을 합니다.

Widget extension이 항상 실행되는 것은 아니기 때문에,

WidgetKit은 Widget을 업데아트 하기 위해 언제 활성화해야하는지 알아야하기 때문이죠.

 

그림으로 보겠습니다. 

처음에 Widget을 rendering하기 위해 Provider에게 timeline을 요청하는 것을 볼 수 있죠. 

아무튼 그럴 때 

이 메소드가 불리는거죠.

코드는 잘 보면 어렵진 않습니다.

현재 Date를 만들고, 현재에 1시간씩 더해주는 것을 볼 수 있습니다.

현재가 2시라면 엔트리 배열에는

[2시, 3시, 4시, 5시, 6시] 가 담기게 되는거죠 (0부터 시작이니까)

그래서 잘 보시면 현재 시간과 Widget에 나와있는 시간이 안맞죠! 

왜냐면 아직 업데이트 할 시간이 아니기 때문입니다.

지금은 byAdding 파라미터에 hour로 들어가있을텐데요,

minute으로 바꾸면 조금 더 쉽게 변화를 보실 수 있습니다.

 

(⚠️system 시간과 안맞는거 주의. 시스템 시간이 1분 지났다고 위젯이 거기에 맞추는거 아님.

내가 currentDate를 만든시간에 따른것⚠️

아무튼 그렇습니다.

1분마다 업데이트 되는 timeline을 받았기 때문이겠죠!?

 

WidgetKit의 매커니즘은 이게 다입니다. 좀 이해가셨나요?

자 그럼 Timeline인스턴스를 만드는 코드를 볼게요.

entries는 내 시간 담은 배열이고..policy라는게 있네요 🤔

policy는

TimelineReloadPolicy타입입니다. 

 

TimelineReloadPolicy


정의가 잘 이해가 안가는데;;; 가장 이른 날짜(the earliest date)를 나타내는 타입이라고 해요.

이 친구는 타입 프로퍼티 3개를 가지고 있습니다.

 

atEnd

after(date:)

never

 

 

atEnd


타임라인의 마지막 날짜가 지난 후 WidgetKit이 새 타임라인을 요청하도록 지정하는 policy입니다.

우리의 코드도 atEnd였죠. 참고로 atEnd는 기본 refresh policy입니다.

자 아까부터 궁금증이 든게 있을 수 있습니다. 

지금이 2시면

[2시, 3시, 4시, 5시, 6시]가 담겨서 넘어갈건데, 그럼 6시 넘으면??????어떻게 될까요?

 

아까 그림을 보겠습니다. 

 

타임라인에 [Now, 1hr, 2hr, 3hr]가 담긴 것을 볼 수 있습니다.

그럼 3hr가 넘어간 후를 봅시다. 

 

 

타임라인을 reload하게됩니다. 

왜냐면!!!!!!!!

아까 언급했듯이 atEnd의 정의는

타임라인의 마지막 날짜가 지난 후 WidgetKit이 새 타임라인을 요청하도록 지정하는 policy이기 때문이죠

"마지막 날짜"가 지났기 때문에 새로운 타임라인을 요청하게 되는거에요. 

저건 애플 예제여서;; 다시 refresh로 never를 넘긴것을 볼 수 있는데요. 일단 저건 무시해주세요.

atEnd로 지정 > 마지막 날짜 지남 > 다시 타임라인 요청 

> policy가 never로 간다~ 이게 아니에요.

이건 따로 나와있는 건 없는데 atEnd로 주고 따로 refresh policy를 주지 않으면 계속

currentDate를 업데이트하고 timeline배열을 다시 생성하는 것 같습니다.

예를들어 6시에 끝났으면 6시 넘어서 timeline을 요청하고

새로운 timeline배열은

[6시, 7시, 8시, 9시, 10시]가 되는거죠.

아까 minute으로 만들어준 친구인데요. 계속 잘 가고 있는 것을 보고 추측한거에요..! 아니라면 말씀해주세요.

 

after(date:)


WidgetKit이 새 타임라인을 요청할 미래 날짜를 지정하는 policy에요.

그림으로 보겠습니다. 

https://developer.apple.com/documentation/widgetkit/keeping-a-widget-up-to-date

 

refresh policy가 after(2 hr)네요. timeline은 [now, 1hr, 2hr, 3hr]구요

ㅇ원래같으면 3hr가 마지막날짜인데, 내가 2hr뒤에 refresh해!!!라는 policy를 넘겼기 때문에 

 

 

2hr가 넘었을 때 다시 timeline을 요청하는 것을 볼 수 있습니다.

또 다시 after(2hr)를 넘겨주는 것을 볼 수 있는데, 이건 예제가 그렇게 되어있어서;;

그런거고 어떻게 짰는지에 따라 달라요

그러니까 일단 after(date)의 동작원리만 알고 넘어가주면 됩니다.

 

never


이 never를 사용하면

WidgetKit은 앱이 WidgetCenter를 사용하여 WidgetKit에 새 타임라인을 요청하도록 지시 할 때 까지

다른 timeline을 요청하지 않는 친구입니다.

 

WidgetCenter는 다른글에서 알아볼게요.

일단 누가 지시할 때 까지 다른 timeline을 요청하지 않는 policy다! 라는 것만 아시면 됩니다. 

 

이렇게 TimelineEntry / TimelineProvider / TimelineReloadPolicy를 공부해봤는데..

좀 감이 오시나요!?

다음글 보러가기

 

Widget관련해서 많은 문서, 샘플코드도 있으니 참고하시면 좋을 것 같아요.

틀린 부분이 있으면 댓글달아주세요!!!

 

developer.apple.com/documentation/widgetkit/creating-a-widget-extension

developer.apple.com/documentation/widgetkit/building_widgets_using_widgetkit_and_swiftui

developer.apple.com/documentation/widgetkit/keeping-a-widget-up-to-date

반응형