Skip to content

Commit

Permalink
Create 240813_WidgetKit,_Timeline,_TimelineReloadPolicy,_TimelineProvโ€ฆ
Browse files Browse the repository at this point in the history
โ€ฆider.md
  • Loading branch information
leeari95 committed Aug 13, 2024
1 parent 36622d8 commit 0676fda
Showing 1 changed file with 121 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# 240813 WidgetKit, Timeline, TimelineReloadPolicy, TimelineProvider

์œ„์ ฏ์˜ ํŠน์„ฑ๊ณผ ํƒ€์ž„๋ผ์ธ์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•ด๋ณด์ž!


8์›” 13์ผ (ํ™”)


# ํ•™์Šต๋‚ด์šฉ

## ์™œ ์œ„์ ฏ์˜ EntryView์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋น„๋™๊ธฐ๋กœ ์„ค์ •ํ•˜๋Š”๋ฐ ์ ์šฉ์ด ์•ˆ๋ ๊นŒ?

์œ„์ ฏ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ •์ ์ธ ๋ทฐ๋‹ค. ์ฆ‰, ์œ„์ ฏ์ด ํ•œ๋ฒˆ ๋ Œ๋”๋ง๋˜๋ฉด ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์ด๋‚˜ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ์— ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ฐ˜์‘ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
๋”ฐ๋ผ์„œ ์œ„์ ฏ์€ 'Timeline' ์ด๋ผ๋Š” ๊ฐœ๋…์„ ์‚ฌ์šฉํ•ด์„œ ์ฝ˜ํ…์ธ ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์•ผํ•œ๋‹ค.
ํƒ€์ž„๋ผ์ธ์€ ์‹œ๊ฐ„์— ๋”ฐ๋ฅธ ์œ„์ ฏ ์ƒํƒœ์˜ ์Šค๋ƒ…์ƒท ์‹œ๋ฆฌ์ฆˆ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ๊ฐ ์Šค๋ƒ…์ƒท์€ ํŠน์ • ์‹œ์ ์— ์–ด๋–ป๊ฒŒ ๋ณด์—ฌ์•ผ ํ•˜๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

## ์œ„์ ฏ์„ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์œผ๋กœ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ• (with Kingfisher)

์œ„์ ฏ ๋‚ด๋ถ€์—์„œ๋Š” ์ง์ ‘์ ์ธ ๋น„๋™๊ธฐ ์š”์ฒญ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ๋”ฐ๋ผ์„œ ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ์ด๋ฏธ์ง€๋‚˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ž‘์—…์€ ํƒ€์ž„๋ผ์ธ์„ ์ƒ์„ฑํ•  ๋•Œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

* `getTimeline(for:in:completion:)` ๋ฉ”์†Œ๋“œ ๋‚ด์—์„œ `ImagePrefetcher(resources:options:completionHandler:)`๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ๋ฏธ๋ฆฌ ๋‹ค์šด๋ฐ›์•„ ์บ์‹œ์— ์ด๋ฏธ์ง€๋ฅผ ์ €์žฅํ•œ๋‹ค.

```swift
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
// ์—…๋ฐ์ดํŠธ ๋‚ ์งœ ์„ค์ •...
let resources: [Resource] = items.compactMap { $0.imageURL }
ImagePrefetcher(resources: resources, options: [.cacheOriginalImage]) { _, _, _ in
let entry = SampleEntry(date: Date(), items: items)
let timeline = Timeline(entries: [entry], policy: /* ์œ„์—์„œ ์„ค์ •ํ•œ ์—…๋ฐ์ดํŠธ ์„ค์ •...*/)

// ์ด๋ฏธ์ง€๋ฅผ ๋ชจ๋‘ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์€ ํ›„ timeline ์ƒ์„ฑ์„ ๋งˆ๋ฌด๋ฆฌํ•œ๋‹ค.
completion(timeline)
}.start()
}
```

* ์ดํ›„ EntryView์—์„œ ์บ์‹œ์— ์ €์žฅ๋œ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ์กฐ๋ฅผ ์„ค์ •ํ•ด์ค€๋‹ค.

```swift
struct SampleWidgetEntryView: View {
// ...

var source: Source? {
guard let imageURL = item.imageURL else { return nil }
return .network(imageURL)
}

var body: some View {
// ...
// ์—ฌ๊ธฐ์„œ source๋ฅผ ํ†ตํ•ด ๋„คํŠธ์›Œํฌ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์š”์ฒญํ•˜๋Š”๋ฐ, ์บ์‹œ์— ์ด๋ฏธ ์กด์žฌํ•ด์„œ ์ฆ‰์‹œ ์ด๋ฏธ์ง€๋ฅผ ์„ค์ •ํ•œ๋‹ค.
KFImage(source: source)
.placeholder {
PlaceholderImage()
.resizable()
.aspectRatio(contentMode: .fill)
}
.resizable()
// ...
}
// ...
}
```

๋„คํŠธ์›Œํฌ๋กœ ์ด๋ฏธ์ง€๊ฐ€ ์•„๋‹Œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ, `getTimeline(for:in:completion:)` ๋ฉ”์†Œ๋“œ์—์„œ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์ด ์™„๋ฃŒ๋œ ํ›„ ํƒ€์ž„๋ผ์ธ์„ ์ƒ์„ฑํ•˜๋„๋ก ๊ตฌ์กฐ๋ฅผ ์žก์•„์ฃผ๋ฉด ๋œ๋‹ค!

## ์œ„์ ฏ์˜ ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ• (TimelineReloadPolicy)

ํƒ€์ž„๋ผ์ธ์„ ์ƒ์„ฑํ•  ๋•Œ `policy`๋ผ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ์— ์—…๋ฐ์ดํŠธ ์ •์ฑ…์„ ์„ค์ •ํ•  ์ˆ˜๊ฐ€ ์žˆ๋‹ค.
์ •์ฑ… ์ข…๋ฅ˜๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

* `.atEnd`
* ๋งˆ์ง€๋ง‰ Entry๊ฐ€ ๋๋‚œ ์‹œ์ ์— ์œ„์ ฏ์ด ๋”์ด์ƒ ์—…๋ฐ์ดํŠธ ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰, ์ฒ˜์Œ์— ์ œ๊ณต๋œ ํƒ€์ž„๋ผ์ธ์ด ๋๋‚˜๋ฉด ๋”์ด์ƒ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ ํ•˜์ง€ ์•Š๋Š”๋‹ค.
* ์ฝ˜ํ…์ธ ๊ฐ€ ์˜ค๋žซ๋™์•ˆ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†๊ฑฐ๋‚˜, ํŠน์ • ์ด๋ฒคํŠธ๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ฐ™์€ ๋‚ด์šฉ์„ ํ‘œ์‹œํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์œ ์šฉํ•˜๋‹ค.
* ์นด์šดํŠธ ๋‹ค์šด์„ ํ‘œ์‹œํ•˜๋Š” ์œ„์ ฏ์ด๋‚˜, ๋‹จ์ผ ์ด๋ฒคํŠธ ์ •๋ณด๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์œ„์ ฏ์— ์ ํ•ฉํ•˜๋‹ค.
* `.after(Date)`
* ์ง€์ •๋œ ๋‚ ์งœ ์ดํ›„์— ์œ„์ ฏ์ด ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋˜๋„๋ก ์„ค์ •ํ•œ๋‹ค. ์„ค์ •ํ•œ ๋‚ ์งœ์— ๋„๋‹ฌํ•˜๋ฉด ์‹œ์Šคํ…œ์ด ์ž๋™์œผ๋กœ ์œ„์ ฏ์„ ์ƒˆ๋กœ ๊ณ ์น˜๊ธฐ ์œ„ํ•ด `getTimeline` ๋ฉ”์†Œ๋“œ๋ฅผ ๋‹ค์‹œ ํ˜ธ์ถœํ•œ๋‹ค.
* ์œ„์ ฏ์ด ์ฃผ๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜์–ด์•ผ ํ•˜๊ฑฐ๋‚˜, ํŠน์ • ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์œผ๋กœ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.
* ๋‚ ์”จ๋‚˜ ๋‰ด์Šค ํ—ค๋“œ๋ผ์ธ์ฒ˜๋Ÿผ ์ž์ฃผ ๊ฐฑ์‹ ๋˜๋Š” ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ์œ„์ ฏ์— ์ ํ•ฉํ•˜๋‹ค.
* `.never`
* ํƒ€์ž„๋ผ์ธ์„ ๊ฐฑ์‹ ํ•˜์ง€ ์•Š๋„๋ก ์„ค์ •ํ•œ๋‹ค. ์œ„์ ฏ์ด ์ฒ˜์Œ ํ‘œ์‹œ๋œ ํ›„ ์ž๋™์œผ๋กœ ๋‹ค์‹œ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š๋Š”๋‹ค.
* ๋งค์šฐ ์ •์ ์ธ ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•˜๋Š” ๊ฒฝ์šฐ ์œ ์šฉํ•˜๋‹ค.
* ์‚ฌ์šฉ์ž์—๊ฒŒ ํ•œ๋ฒˆ๋งŒ ๋ณด์—ฌ์ค˜๋„ ๋˜๋Š” ์„ค์ •์ด๋‚˜, ๋„์›€๋ง, ๋˜๋Š” ์ด๋ฒคํŠธ ์ฐธ์—ฌ ํ›„ ๋ฐ”๋€Œ์ง€ ์•Š๋Š” ๊ณ ์ •๋œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ์œ„์ ฏ์— ์ ํ•ฉํ•˜๋‹ค.

๋‚˜๋Š” .after(Date)๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์œ„์ ฏ ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ๋ฅผ ์„ค์ •ํ•˜์˜€๋Š”๋ฐ, ์ •ํ™•ํ•˜๊ฒŒ 15๋ถ„ ๊ฐ„๊ฒฉ์œผ๋กœ ์œ„์ ฏ์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์žˆ์ง€๋Š” ์•Š์€ ๊ฒƒ ๊ฐ™๋‹ค. ์ด์œ ๊ฐ€ ๊ถ๊ธˆํ•ด์„œ ์ฐพ์•„๋ณด์•˜๋‹ค:
* ์œ„์ ฏ์˜ ์—…๋ฐ์ดํŠธ๋Š” ์‹œ์Šคํ…œ์ด ์ •ํ•ด์ง„ `์˜ˆ์‚ฐ` ๋‚ด์—์„œ ํ—ˆ์šฉ๋œ๋‹ค. ์ด ์˜ˆ์‚ฐ์€ ๋ฐฐํ„ฐ๋ฆฌ์™€ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ์‹œ์Šคํ…œ์—์„œ ์ œํ•œํ•œ๋‹ค๊ณ  ํ•œ๋‹ค. ([๊ณต์‹๋ฌธ์„œ](https://developer.apple.com/documentation/widgetkit/keeping-a-widget-up-to-date#Plan-reloads-within-a-budget))
* ๋„ˆ๋ฌด ์ž์ฃผ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ์‹œ์Šคํ…œ์ด ์ด๋ฅผ ์ œํ•œํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์˜๋ฏธ๋‹ค.
* ๋”ฐ๋ผ์„œ ์ด ์ ์„ ๊ณ ๋ คํ•ด ๊ผญ ํ•„์š”ํ•œ ์‹œ๊ธฐ์— ์—…๋ฐ์ดํŠธ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ณ„ํšํ•ด์•ผํ•˜๋ฉฐ, ๋ถˆํ•„์š”ํ•œ ์—…๋ฐ์ดํŠธ๋ฅผ ํ”ผํ•ด์•ผํ•œ๋‹ค.

Apple์—์„œ ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ ์‹œ๊ฐ„์„ ๋ช…์‹œ์ ์œผ๋กœ ๊ถŒ์žฅํ•˜๊ณ  ์žˆ์ง€๋Š” ์•Š์ง€๋งŒ, ์œ„์ ฏ์˜ ์—…๋ฐ์ดํŠธ ๋นˆ๋„๋Š” ๋ฐฐํ„ฐ๋ฆฌ ์†Œ๋ชจ์™€ ์„ฑ๋Šฅ์„ ๊ณ ๋ คํ•˜์—ฌ ์‹ ์ค‘ํ•˜๊ฒŒ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์„ค๋ช…ํ•˜๊ณ  ์žˆ๋‹ค.

๊ณต์‹๋ฌธ์„œ์—์„œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ 15๋ถ„์—์„œ 1์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์ด ํ•ฉ๋ฆฌ์ ์ธ ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ๋กœ ์—ฌ๊ฒจ์ง„๋‹ค๋Š” ๋‚ด์šฉ์ด ์žˆ๊ธฐ๋Š” ํ•˜๋‹ค.


## TimelineProvider์˜ ์ฃผ์š” ๋ฉ”์„œ๋“œ ์—ญํ• 

* `placeholder(in:)`
* ๋ฐ์ดํ„ฐ๊ฐ€ ์ค€๋น„๋˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ ๊ธฐ๋ณธ UI๋ฅผ ์ œ๊ณตํ•ด์ฃผ๋Š” ๋ฉ”์†Œ๋“œ๋กœ ๋กœ๋”ฉ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค€๋‹ค.
* ์œ„์ ฏ์ด ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๊ธฐ ์ „์— ์ž ์‹œ ๋ณด์—ฌ์ค„ ๊ธฐ๋ณธ์ ์ธ ์ฝ˜ํ…์ธ ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
* ์ฃผ๋กœ ์œ„์ ฏ์ด ๋กœ๋“œ๋˜๊ธฐ ์ „, ๋ฐ์ดํ„ฐ๊ฐ€ ์ค€๋น„๋˜์ง€ ์•Š์•˜์„ ๋•Œ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ณธ์ ์ธ UI๋ฅผ ์ •์˜ํ•œ๋‹ค.
* Entry๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋˜์–ด์žˆ์ง€๋งŒ, ํ•ด๋‹น Entry๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์œ„์ ฏ์˜ ๋ทฐ๋ฅผ ๋ชจ๋‘ ์„ค์ •ํ•œ ํ›„ ์Šค์ผˆ๋ ˆํ†ค ํ˜•ํƒœ๋กœ ๋ณด์—ฌ์ง€๊ฒŒ ๋œ๋‹ค.

> `placeholder(in:)`๋กœ ๋ทฐ๊ฐ€ ์„ธํŒ…๋˜์—ˆ์ง€๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œ์‹œํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. (์•„๋ž˜ ์˜ˆ์‹œ ์‚ฌ์ง„)
![IMG_AC598843FA37-1](https://github.com/user-attachments/assets/63b90e91-f554-4396-bf85-833683911c8c)

* `getSnapshot(in:completion:)`
* ์œ„์ ฏ์ด ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ƒํƒœ์—์„œ ํ‘œ์‹œํ•  ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
* ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ€์žฅ ์ตœ๊ทผ์— ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ ๋˜๋Š” ๊ณ ์ •๋œ ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์œ„์ ฏ์˜ ๋ชจ์Šต์ด ์–ด๋–ป๊ฒŒ ๋ณด์ผ์ง€ ๋ฏธ๋ฆฌ ๋ณด์—ฌ์ค€๋‹ค.
* `getTimeline(in:completion:)`
* ์ด ๋ฉ”์„œ๋“œ๋Š” ์‹ค์ œ๋กœ ์œ„์ ฏ์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ํ‘œ์‹œ๋  ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๊ณ , ํƒ€์ž„๋ผ์ธ์„ ๊ตฌ์„ฑํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
* ์œ„์ ฏ์ด ์ฃผ๊ธฐ์ ์œผ๋กœ ๊ฐฑ์‹ ๋  ๋ฐ์ดํ„ฐ ๋ฆฌ์ŠคํŠธ, ํƒ€์ž„๋ผ์ธ์„ ์ƒ์„ฑํ•˜์—ฌ ํŠน์ • ์‹œ๊ฐ„๋Œ€์— ์–ด๋–ค ๋ฐ์ดํ„ฐ๊ฐ€ ํ‘œ์‹œ๋ ์ง€๋ฅผ ์ •์˜ํ•œ๋‹ค.
* ๋˜ํ•œ ๋‹ค์Œ ์—…๋ฐ์ดํŠธ ์‹œ์ ์„ ์„ค์ €ํ•˜์—ฌ ์œ„์ ฏ์ด ์–ธ์ œ ๋‹ค์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ• ์ง€ ๊ฒฐ์ •ํ•œ๋‹ค.

---


# ์ฐธ๊ณ  ๋งํฌ


- [https://developer.apple.com/documentation/widgetkit/keeping-a-widget-up-to-date](https://developer.apple.com/documentation/widgetkit/keeping-a-widget-up-to-date)
- [https://developer.apple.com/documentation/widgetkit/making-network-requests-in-a-widget-extension](https://developer.apple.com/documentation/widgetkit/making-network-requests-in-a-widget-extension)

0 comments on commit 0676fda

Please sign in to comment.