티스토리 뷰

위젯의 핵심인 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개의 함수를 구현해야 합니다.

  1. func placeholder(in context: Self.Context) -> Self.Entry

데이터를 불러오기 전(getSnapshot)에 보여줄 placeholder

  1. func getSnapshot(in context: Self.Context, completion: @escaping (Self.Entry) -> Void)

위젯 갤러리에서 위젯을 고를 때 보이는 샘플 데이터를 보여줄때 해당 메소드 호출

API를 통해서 데이터를 fetch하여 보여줄때 딜레이가 있는 경우 여기서 샘플 데이터를 하드코딩해서 보여주는 작업도 가능

context.isPreview가 true인 경우 위젯 갤러리에 위젯이 표출되는 상태

  1. 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 란 대략적으로 예를 들면 스마트 스택을 가진 위젯에서 시간에 따라서 어떠한 위젯을 보여줄지 결정하게 되는데 보여줄 위젯들의 우선순위를 정하기 위한 변수라고 생각하시면 될 것 같습니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함