WidgetKit using SwiftUI — iOS14

Balaji
6 min readApr 1, 2021

WidgetKit

Let’s have a Quick view about adding Multiple widgets to HomeScreen.

WidgetKit is a framework that is introduced in iOS14.Widgets should be written in SwiftUI.Using WidgetKit, developers can create widgets that can be displayed between the apps on the home screen.

Widgets can be configured in two different ways:

StaticConfiguration — It can be used when no configuration is needed from the user.

IntentConfiguration — It can be used when the configuration is needed from the user. Users can customize the widget by using Siri intents.

Example

Creating Widget Extension

Adding a widget extension : — File → New → Target

Search for “widget”, select Widget Extension and click Next:

Note,Uncheck Include Configuration Intent

Click activate-scheme

Now the widget is created After Adding Extension Target.

TimelineEntry struct is used to hold the data in single structure for widget content.

struct SimpleEntry: TimelineEntry {public let date: Date
let gallery : GetPhotoAsset
}

Create Supporting Files For Widget Model

Timeline Provider having two protocol

The provider contains the refresh logic

snapshot(for: with: completion) — Used to load the initial data for the WidgetsView.

timeline (for: with: completion) — Used to create more entries and update the data using Time intervals. Using the function timeline the refresh entry is created and also refreshing your widget..

struct Provider: TimelineProvider {public typealias Entry = SimpleEntrypublic func snapshot(with context: Context, completion: @escaping (SimpleEntry) -> ()) {let entry = SimpleEntry(date: Date(), gallery: GetPhotoAsset.getAllPhotos())completion(entry)}public func timeline(with context: Context, completion: @escaping (Timeline<Entry>) -> ()) {var entries: [SimpleEntry] = []let entry = SimpleEntry(date: Date(), gallery: GetPhotoAsset.getAllPhotos())entries.append(entry)let timeline = Timeline(entries: entries, policy: .atEnd)completion(timeline)}
}

You can custom your widget view as per your data requirements.

struct SampleTimelineWidgetEntryView : View { var entry: Provider.Entry@Environment(\.widgetFamily) var family@ViewBuildervar body: some View { switch family {case .systemSmall://** ...........  Design as your WishText("Photos").font(Font.headline.bold())Text("\(entry.gallery.allPhotos.count)")........... **//case .systemMedium://** ...........  Design as your WishText("Photos").font(Font.headline.bold())Text("\(entry.gallery.allPhotos.count)")........... **//default://** ...........  Design as your Wish ...........Text("Photos").font(Font.largeTitle.bold())Text("\(entry.gallery.allPhotos.count)")........... **//

PlaceholderView — is an initial Representation of your widget content. It displayed data to the user before you loaded with content.

struct PlaceholderView : View {var body: some View {Text("Loading...")}}

Kind — A unique identifier for the widget. The identifier is used to reload your widget.

struct SampleTimelineWidget: Widget {private let kind: String = "SampleTimelineWidget"public var body: some WidgetConfiguration {         StaticConfiguration(kind: kind, provider: Provider(),     placeholder: PlaceholderView()) { entry in         SampleTimelineWidgetEntryView(entry: entry)
}
.configurationDisplayName("My Widget").description("This is an example widget.").supportedFamilies([.systemSmall,.systemMedium])}}

In the code above, a new widget named SampleTimelineWidget is created. The body contains the initialisation of the widget.

Content closure — is used to configure the three Widget size families to be displayed to the user and size can be systemSmall, systemMedium or systemLarge custom by using enivironment widget family.

Source code for TimelineProvider

Now we are going to see an example for adding additional widgets.

For Adding Additional Widgets : — File → New → Swift File

Name it AdditionalTimelineWidget and make sure Make sure your SampleTimelineWidgetExtension target is selected.

Copy all the Structs from SampleTimelineWidgets to AdditionalTimelineWidget

Note,Change following struct name Provider, Entry, View, Placholder and widget.

struct AdditionalProvider: TimelineProvider { ... }struct AdditionalSimpleEntry: TimelineEntry { ... }struct AdditionalPlaceholderView : View { ... }struct AdditionalTimelineWidgetEntryView : View { ... }struct  AdditionalTimelineWidget: Widget { ... }

Note, set target @main for widget bundle.(Remove @main target in both widgets struct class)

widgetBundle” is used to create multiple widgets by using the same Extension target. so we can create multiple widgets that look like this.

We can use reloadtimelines to update the data sync from the app to the widgets.

WidgetCenter.shared.reloadAllTimelines()

In our project i am using it in scene delegate .

import UIKit
import WidgetKit
func sceneWillResignActive(_ scene: UIScene) {// Called when the scene will move from an active state to an inactive state.// This may occur due to temporary interruptions (ex. an incoming phone call).WidgetCenter.shared.reloadAllTimelines()}

Intent configuration

Adding Configuration file : — File → New → SiriKit Intent Definition File

Name it SampleIntentConfig and make sure Make sure your MultipleWidgets and SampleTimelineWidgetExtension targets are selected.

Tap “+” icon to create a New Intent File

Named the Intent File SampleIntentConfig.

In Custom Intent Make sure to select “View” instead of “Do” .

Category -> Information ->View

Untick the Default options in Custom Intent and tick the option Widgets.

The Custom intent is look like this

Tap “+” Add to create a New Parameter name it as “sample”,

You can Choose Type based on your Configuration. Note, For Our Project Choose Add Enum Type.

Create cases as your Configuration

Copy all the Structs from SampleTimelineWidgets to SampleIntentWidgets.

Note,Change delegate TimelineProvider to IntentTimelineProvider.

import WidgetKit
import SwiftUI
import Photos
import Intents
struct SampleIntentProvider: IntentTimelineProvider {typealias Entry = SampleIntentSimpleEntrytypealias Intent = SampleIntentConfigIntentfunc snapshot(for configuration: SampleConfigIntent, with context: Context, completion: @escaping (SampleIntentSimpleEntry) -> ()) {<#code#>}func timeline(for configuration: SampleConfigIntent, with context: Context, completion: @escaping (Timeline<SampleIntentSimpleEntry>) -> ()) {<#code#>}}

SampleIntentWidgets code

Adding one more Supporting files for our Example for intent View data

Our example for Intent Configuration File is look like this

Finally add IntentWidget in WidgetBundle.

Conclusion

Creating Widgets using widget kit framework You can customization of your widgets depending on the data info of different sizes. Using intent configuration method Show data to the user with different configurations.Adding Multiple widgets in same Target.

The completed project can be found in GitHub.

--

--