티스토리 뷰
위젯의 핵심인 TimelineProvider에 대해 알아보겠습니다.
처음 설치했을때 샘플로 되어있는 코드입니다.
struct Provider: TimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date())
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date())
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
먼저 TimelineProvider에 들어가보면
public protocol TimelineProvider {
/// A type that specifies the date to display a widget, and, optionally,
/// indicates the current relevance of the widget's content.
associatedtype Entry : TimelineEntry
/// An object that contains details about how a widget is rendered, including its size and whether it
/// appears in the widget gallery.
///
/// For more information, see <doc:TimelineProviderContext>.
typealias Context = TimelineProviderContext
/// Provides a timeline entry representing a placeholder version of the
/// widget.
///
/// When WidgetKit displays your widget for the first time, it renders the widget's
/// view as a placeholder. A placeholder view displays a generic representation of
/// your widget, giving the user a general idea of what the widget shows. WidgetKit
/// calls `placeholder(in:)` to request an entry representing
/// the widget's placeholder configuration. For example, the game status widget
/// would implement this method as follows:
///
/// ```swift
/// struct GameStatusProvider: TimelineProvider {
/// func placeholder(in context: Context) -> SimpleEntry {
/// GameStatusEntry(date: Date(), gameStatus: "—")
/// }
/// }
///
/// In addition, WidgetKit may render your widget as a placeholder if users choose to hide sensitive
/// information on Apple Watch or the iPhone Lock Screen. To learn more about redacting sensitive
/// data, see <doc:Creating-a-Widget-Extension>.
///
/// > Important: `placeholder(in:)` is synchronous and returns
/// a `TimelineEntry` immediately. Return from `placeholder(in:)` as quickly
/// as possible.
///
/// - Parameter context: An object that describes the context in which to
/// show the widget.
/// - Returns: A timeline entry that represents a placeholder version of the
/// widget.
func placeholder(in context: Self.Context) -> Self.Entry
/// Provides a timeline entry that represents the current time and state of a
/// widget.
///
/// WidgetKit calls `getSnapshot(in:completion:)` when the widget
/// appears in transient situations. If `context.isPreview` is `true`, the
/// widget appears in the widget gallery. In that case, call the
/// `completion` handler as quickly as possible, perhaps supplying sample
/// data if it could take more than a few seconds to fetch or calculate the
/// widget's current state.
/// - Parameters:
/// - context: An object describing the context to show the widget in.
/// - completion: The completion handler to call after you create the
/// snapshot entry.
func getSnapshot(in context: Self.Context, completion: @escaping (Self.Entry) -> Void)
/// Provides an array of timeline entries for the current time and,
/// optionally, any future times to update a widget.
/// - Parameters:
/// - context: An object describing the context to show the widget in.
/// - completion: The completion handler to call after you create the
/// timeline.
func getTimeline(in context: Self.Context, completion: @escaping (Timeline<Self.Entry>) -> Void)
}
샘플에 있는 3개의 함수를 구현해야 합니다.
- func placeholder(in context: Self.Context) -> Self.Entry
데이터를 불러오기 전(getSnapshot)에 보여줄 placeholder
- func getSnapshot(in context: Self.Context, completion: @escaping (Self.Entry) -> Void)
위젯 갤러리에서 위젯을 고를 때 보이는 샘플 데이터를 보여줄때 해당 메소드 호출
API를 통해서 데이터를 fetch하여 보여줄때 딜레이가 있는 경우 여기서 샘플 데이터를 하드코딩해서 보여주는 작업도 가능
context.isPreview가 true인 경우 위젯 갤러리에 위젯이 표출되는 상태
- func getTimeline(in context: Self.Context, completion: @escaping (Timeline<Self.Entry>) -> Void)
홈화면에 있는 위젯을 언제 업데이트 시킬것인지 구현하는 부분
샘플 코드를 보면
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
타임 라인이라고 적혀있는데 Timeline 정책에는
public struct TimelineReloadPolicy : Equatable {
/// A policy that specifies that WidgetKit requests a new timeline after
/// the last date in a timeline passes.
/// 정해놓은 정책의 시간이 끝났을때 다시 호출
public static let atEnd: TimelineReloadPolicy
/// A policy that specifies that the app prompts WidgetKit when a new
/// timeline is available.
/// 임의로 업데이트 하지않는 이상 업데이트 X
public static let never: TimelineReloadPolicy
/// A policy that specifies a future date for WidgetKit to request a new
/// timeline.
/// 정해진 날짜 이후에 업데이트
public static func after(_ date: Date) -> TimelineReloadPolicy
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (a: TimelineReloadPolicy, b: TimelineReloadPolicy) -> Bool
}
atEnd, never, after 3개의 타임라인 정책이 있습니다.
TimelineEntry
struct SimpleEntry: TimelineEntry {
let date: Date
}
Timeline 속에서 자주 등장하는 TimlineEntry 입니다. 데이터 모델이라고 보셔도 무방해보입니다.
public protocol TimelineEntry {
/// The date for WidgetKit to render a widget.
var date: Date { get }
/// The relevance of a widget’s content to the user.
var relevance: TimelineEntryRelevance? { get }
}
시간 정책을 가져가서 그런지 date 변수를 필수적으로 가져가야 합니다.
밑에 relevance 란 대략적으로 예를 들면 스마트 스택을 가진 위젯에서 시간에 따라서 어떠한 위젯을 보여줄지 결정하게 되는데 보여줄 위젯들의 우선순위를 정하기 위한 변수라고 생각하시면 될 것 같습니다.
'Widget' 카테고리의 다른 글
iOS Widget - 위젯 파일 구조 파악(3)- View (0) | 2023.03.04 |
---|---|
iOS Widget - 위젯 파일 구조 파악(1) - Widget (0) | 2023.03.02 |
iOS Widget - 위젯 타겟생성시 생기는 파일 구조 파악(2) - WidgetBundle (0) | 2023.03.01 |
iOS Widget - 위젯 타겟생성시 생기는 파일 구조 파악(1) - WidgetBundle (0) | 2023.02.28 |
iOS Widget - Add WidgetExtension (위젯 추가하기) (0) | 2023.02.27 |