Create Widget Extension
Published by @SoNiceInfo at 7/5/2020
By using Widgets, users can diplay App contents on iOS Home and macOS Notification Center.
What you need to know about Widgets
Widgets Size
The size of widgets are defined at supportedFamilies. There are 3 types, .systemSmall
(2x2 Size), .systemMedium
(4x2 Size), .systemLarge
(4x4 Size).
StaticConfiguration and IntentConfiguration
There 2 type in Widgets, StaticConfiguration
and IntentConfiguration
.
StaticConfiguration
: Users don't need any configuration on widgets, for example, widgets that display lates news.IntentConfiguration
: Users can configure on widgets, for example, widgtes that need location info to show weather.
TimelineEntry and Timeline
Widgets don't support real-time update. You need to provide contents with display time to widgets. You need to know TimelineEntry and Timeline.TimelineEntry
Object has the contents and the Date-type date like below. (In this case, content is something Int type.) You set date to date when you want to display the contents.
struct SimpleEntry: TimelineEntry {
var date: Date
var int: Int
}
Timeline is an array of TimelineEntry
objects. Reload of Timeline is occured at when the last TimelineEntry was displayed (.atEnd
), after the specified time has elapsed (.after
), App reload content through WidgetCenter(.never
). Timeline is provided to widgets by Provider
conforming to TimelineProvider
.
Snapshot
Snapshot is used for previewing widgets and displaying them instantly in the Widget Gallery. A TimelineEntry
is provided to the Snapshot. A mock value should be in the TimelineEntry
until the contents will be fetched from servers.
Provider
The Provider is an object that provides the above timeline and Snapshot to the widget.
With StaticConfiguration、you use a Provider conforming to TimelineProvider
.
With IntentConfiguration、you use a Provider conforming to IntentTimelineProvider
.
struct Provider: TimelineProvider {
public typealias Entry = SimpleEntry
public func snapshot(with context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), int: Int.random(in: 1..<100))
completion(entry)
}
public func timeline(with context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let date = Date()
let refreshDate = Calendar.current.date(byAdding: .minute, value: 1, to: date)!
print(refreshDate)
let timeline = Timeline(entries: [SimpleEntry(date: date, int: Int.random(in: 1..<100)), SimpleEntry(date: refreshDate, int: Int.random(in: 1..<100))], policy: .after(refreshDate))
completion(timeline)
}
}
Placeholder
The Placeholder displays the general look and feel of the widget. You will be able to use .redacted(reason: .placeholder)
to implement.
iOS 14 beta 3 introduces .redacted(reason: .placeholder) to generate a placeholder view of any SwiftUI view
— Jordan Singer (@jsngr) July 23, 2020
Here's a few real examples: https://t.co/m0iOlbMRCa pic.twitter.com/JUIrLdDP2F
kind
The kind is a string that uniquely identifies the widget. Like com.example.widget
, a string like the Bundle indentifier would be good.
Add Widget Extension
Widget technically refers to the Widget Extension that comes with your app.
Go to File → New → Target... then dialog appears, select Widget Extension
and press Select.
Check Include Configuration Intent to use IntentConfiguration.
Enter the appropriate Product Name and Finish.
Press Activate when asked when activating "PRODUCT_NAME" scheme.PRODUCT_NAME.swift
will be added in the new directory.
You are now ready to create a Widget Extension.
Build
Select your widget in "Set the active scheme" at top left and built it. IntentConfiguration widgets cannot be test with Xcode 12 beta and iOS Simulator. Let's wait for them to fix it.
References
Creating a Widget Extension | Apple Developer DocumentationWidgets - System Capabilities - iOS - Human Interface Guidelines - Apple Developer