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.

Creating a Simple Widget in SwiftUI: A Step-by-Step Tutorial

In this tutorial, we'll walk through the process of creating a basic widget for iOS using SwiftUI and the WidgetKit framework. We'll build a widget that displays the current time and a fun emoji. Let's dive in!

Step 1: Setting Up the Widget

First, we need to create a new target for our widget. In Xcode, go to File > New > Target and select "Widget Extension". Name it "WidgetTestWidget" and make sure to select SwiftUI as the interface.

Step 2: Implementing the TimelineProvider

The TimelineProvider is responsible for providing the content for our widget. Let's break down the Provider struct:

struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date(), emoji: "")
    }

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

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

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

        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    }
}
  • The placeholder function provides a sample entry for when the widget is first added.
  • getSnapshot is called when the system needs a quick snapshot of the widget's state.
  • getTimeline generates a timeline of entries. In this case, we're creating 5 entries, each an hour apart.

Step 3: Defining the Entry

The SimpleEntry struct represents a single instance of our widget's content:

struct SimpleEntry: TimelineEntry {
    let date: Date
    let emoji: String
}

Step 4: Creating the Widget View

Now, let's design how our widget will look:

struct WidgetTestWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        VStack {
            Text("Hello Welcome to William Jiamin's Channel!")
            Text("Time:")
            Text(entry.date, style: .time)
            Text("Emoji:")
            Text(entry.emoji)
        }
    }
}

This view displays a welcome message, the current time, and an emoji.

Step 5: Configuring the Widget

Finally, we'll set up the main widget structure:

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()
            }
        }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
    }
}

Here, we're using a StaticConfiguration and providing our custom view. We also add a background color for iOS 17 and above.

Step 6: Adding a Preview

To see how our widget looks, we can add a preview:

#Preview(as: .systemSmall) {
    WidgetTestWidget()
} timeline: {
    SimpleEntry(date: .now, emoji: "")
    SimpleEntry(date: .now, emoji: "")
}

This preview shows how the widget will appear in the small size, with two different emojis.

Conclusion

And there you have it! We've created a simple but functional widget that displays the current time and a fun emoji. This widget updates every hour, showing how dynamic content can be displayed in iOS widgets.

Remember to add your widget to your app's capabilities and test it thoroughly on different devices and in different sizes. Happy coding!