Mobile Development 11 min read

iOS 14 WidgetKit Development Guide: Creating, Configuring, and Communicating Widgets

This article provides a comprehensive tutorial on developing iOS 14 WidgetKit widgets, covering widget sizes, Xcode target creation, configuration options, essential SwiftUI components, timeline refresh mechanisms, communication between the main app and widget via App Groups and Keychain, as well as troubleshooting common issues.

Beike Product & Technology
Beike Product & Technology
Beike Product & Technology
iOS 14 WidgetKit Development Guide: Creating, Configuring, and Communicating Widgets

iOS 14 introduced WidgetKit, allowing developers to add small, medium, and large widgets to the home screen or macOS Notification Center. Widgets can display up-to-date information and support deep‑link navigation to any part of the main app.

Widget sizes : three predefined families (systemSmall, systemMedium, systemLarge) with different dimensions for various device resolutions.

1. Creating a Widget target

In Xcode 12 (or later) choose File → New → Target → Widget Extension . Two configuration types are available:

StaticConfiguration : for widgets without user‑configurable properties.

IntentConfiguration : for widgets that expose configurable parameters via SiriKit intents.

The “Include Configuration Intent” checkbox determines which configuration Xcode uses.

2. Core Widget components

kind : a string identifier for the widget.

Provider : conforms to TimelineProvider and supplies a timeline of TimelineEntry objects.

Placeholder : a SwiftUI view shown before real data loads.

Content Closure : renders the widget UI using the entry supplied by the provider.

3. Required provider functions

func placeholder(in context: Context) -> SimpleEntry {
    SimpleEntry(date: Date(), model: LJWidgetModel.preview_widget)
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
    let entry = SimpleEntry(date: Date(), model: LJWidgetModel.preview_widget)
    completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline
) -> ()) {
    let date = Calendar.current.date(byAdding: .hour, value: 12, to: Date()) ?? Date()
    LJWidgetAPI.loadData { (model, error) in
        guard let model = model else {
            let timeline = Timeline(entries: [SimpleEntry(date: date, model: LJWidgetModel.preview_widget)], policy: .after(date))
            completion(timeline)
            return
        }
        let timeline = Timeline(entries: [SimpleEntry(date: date, model: model)], policy: .after(date))
        completion(timeline)
    }
}

4. Data model

struct SimpleEntry: TimelineEntry {
    let date: Date
    let model: LJWidgetModel
}

5. Widget view

struct LJWidgetEntryView: View {
    var entry: Provider.Entry
    @Environment(\.widgetFamily) var family

    @ViewBuilder
    var body: some View {
        switch family {
        case .systemSmall:
            LJWidgetSmall(entry.model.small).previewLayout(.sizeThatFits)
        case .systemMedium:
            LJWidgetMedium(entry.model.medium).previewLayout(.sizeThatFits)
        case .systemLarge:
            LJWidgetLarge(entry.model.large).previewLayout(.sizeThatFits)
        @unknown default:
            Text("unknown")
        }
    }
}

6. Widget declaration

struct LJWidget: Widget {
    let kind = "LJWidget"
    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
            LJWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
        .supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
    }
}

7. Refresh mechanisms

Automatic refresh: the timeline defines future dates; when a date is reached WidgetKit requests a new timeline.

Manual refresh: push notifications or explicit calls to WidgetCenter.shared.reloadAllTimelines() from the main app.

8. Mixing Objective‑C and Swift

To call Objective‑C code from Swift, create a bridging header (e.g., Project‑Bridging‑Header.h ) and import the OC headers. To call Swift from Objective‑C, Xcode generates a Project‑Swift.h file automatically.

9. Communication between the main app and the widget

Because the widget runs in a separate process, shared data must be stored in a common container.

• App Group – configure the same App Group identifier for both targets, then read/write a file:

// Main app writes to shared file
NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.simon.app.test"];
NSURL *fileURL = [groupURL URLByAppendingPathComponent:@"appGroup.txt"];
[textField.text writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:nil];
// Widget reads from shared file
NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.simon.app.test"];
NSURL *fileURL = [groupURL URLByAppendingPathComponent:@"appGroup.txt"];
NSString *str = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:nil];
self.shareLabel.text = str;

• Keychain Sharing – store encrypted user data in the keychain and enable the same keychain access group for both targets.

10. Common issues and solutions

Intent configuration not found – deselect Intent when not needed.

Widget preview not showing in Xcode 12 beta – switch to the new build system.

Swift version mismatch – set Swift language version to 5.0.

AppGroup file missing – ensure the .entitlements file is added to both targets.

Multiple command errors – use Legacy Build System or remove duplicate Info.plist copies.

Library not loaded errors – verify WidgetKit framework is linked and the deployment target supports iOS 14.

References:

WidgetKit Documentation

SwiftUI Tutorial

Mobile DevelopmentiOSSwiftSwiftUIWidgetKitAppGroupKeychain
Beike Product & Technology
Written by

Beike Product & Technology

As Beike's official product and technology account, we are committed to building a platform for sharing Beike's product and technology insights, targeting internet/O2O developers and product professionals. We share high-quality original articles, tech salon events, and recruitment information weekly. Welcome to follow us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.