Customize Consent Preferences

We use cookies to help you navigate efficiently and perform certain functions. You will find detailed information about all cookies under each consent category below.

The cookies that are categorized as "Necessary" are stored on your browser as they are essential for enabling the basic functionalities of the site. ... 

Always Active

Necessary cookies are required to enable the basic features of this site, such as providing secure log-in or adjusting your consent preferences. These cookies do not store any personally identifiable data.

Functional cookies help perform certain functionalities like sharing the content of the website on social media platforms, collecting feedback, and other third-party features.

Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics such as the number of visitors, bounce rate, traffic source, etc.

Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.

Advertisement cookies are used to provide visitors with customized advertisements based on the pages you visited previously and to analyze the effectiveness of the ad campaigns.

WidgetKit Series 4 : Creating a Dynamic Day of the Week Widget in SwiftUI

In this tutorial, we'll walk through the process of creating a dynamic widget for iOS that displays the current day of the week along with a corresponding emoji. This widget updates throughout the week, providing a fun and informative addition to your users' home screens.

Setting Up the Widget

First, let's break down the main components of our widget:

  1. Provider: Manages the timeline of our widget's content.
  2. DateEntry: Represents the data for each widget update.
  3. WidgetTestWidgetEntryView: Defines the widget's user interface.
  4. WidgetTestWidget: Configures the widget itself.

The Provider

The Provider struct conforms to TimelineProvider and is responsible for generating the content timeline for our widget:

struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> DateEntry {
        DateEntry(date: Date())
    }

    func getSnapshot(in context: Context, completion: @escaping (DateEntry) -> ()) {
        let entry = DateEntry(date: Date())
        completion(entry)
    }

    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [DateEntry] = []

        let currentDate = Date()
        for hourOffset in 0 ..< 5 {
            let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
            let entry = DateEntry(date: entryDate)
            entries.append(entry)
        }

        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    }
}

This provider creates a timeline with entries for the next 5 hours, ensuring our widget stays up-to-date throughout the day.

The DateEntry

Our DateEntry struct holds the date information and provides a computed emoji property based on the day of the week:

struct DateEntry: TimelineEntry {
    let date: Date

    var emoji: String {
        let weekday = Calendar.current.component(.weekday, from: date)
        switch weekday {
        case 1: return "" // Sunday
        case 2: return "" // Monday
        case 3: return "" // Tuesday
        case 4: return "" // Wednesday
        case 5: return "" // Thursday
        case 6: return "" // Friday
        case 7: return "" // Saturday
        default: return ""
        }
    }
}

This clever use of a computed property allows us to display a different emoji for each day of the week.

The Widget View

The WidgetTestWidgetEntryView struct defines how our widget looks:

struct WidgetTestWidgetEntryView : View {
    var entry: DateEntry

    var body: some View {
        ZStack {
            ContainerRelativeShape()
                .fill(LinearGradient(
                    gradient: Gradient(colors: [.cyan, .green]),
                    startPoint: .topLeading,
                    endPoint: .bottomTrailing
                ))

            VStack {
                Text("\(entry.emoji)")
                    .font(.system(size: 50))
                Text(entry.date.formatted(.dateTime.weekday(.wide)))
                    .font(.title3)
                    .fontWeight(.bold)
                    .foregroundStyle(.white.opacity(0.7))

                Text(entry.date.formatted(.dateTime.day()))
                    .font(.largeTitle)
                    .bold()
                    .foregroundStyle(.white.opacity(0.7))
            }
            .padding()
        }
    }
}

This view creates a visually appealing widget with a gradient background, the day's emoji, the name of the day, and the date.

The Widget Configuration

Finally, we define our widget using the WidgetTestWidget struct:

struct WidgetTestWidget: Widget {
    let kind: String = "WidgetTestWidget"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
            if #available(iOS 17.0, *) {
                WidgetTestWidgetEntryView(entry: entry)
                    .containerBackground(.fill.tertiary, for: .widget)
            } else {
                WidgetTestWidgetEntryView(entry: entry)
                    .padding()
                    .background(Color.black)
            }
        }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
        .contentMarginsDisabled()
    }
}

This configuration sets up our widget with the appropriate provider and view, and includes compatibility checks for different iOS versions.

Conclusion

With this code, we've created a dynamic, visually appealing widget that displays the current day of the week along with a fun emoji. The widget updates throughout the week, providing users with a quick and enjoyable way to check the day at a glance.

Remember to add this widget to your app's target and enable it in the capabilities section of your project settings. Happy coding!