glance_widget_ios 2.0.1
glance_widget_ios: ^2.0.1 copied to clipboard
iOS implementation of the glance_widget plugin using WidgetKit.
glance_widget_ios #
iOS implementation of the glance_widget plugin using WidgetKit.
Features #
- Seven widget templates: Simple, Progress, List, Calendar, Image, Chart and Gauge
- Per-instance configuration: place two widgets from one template and point each
at a different
widgetId(long-press → Edit Widget) - Instant updates when app is in foreground (no budget limit!)
- Theme support with dark/light modes
- Widget tap actions sent back to Flutter
- Widget Push Updates support (iOS 26+)
Requirements #
- iOS 17.0 or higher
- Xcode 15.0 or higher
- Swift 5.9 or higher
Set your app's deployment target to iOS 17 in Xcode (Runner → General →
Minimum Deployments), and in ios/Podfile as well if you still use CocoaPods.
Under Swift Package Manager the Xcode value reaches
FlutterGeneratedPluginSwiftPackage only through flutter build ios
(--config-only is enough): flutter pub get regenerates that manifest at
Flutter's 15.0 default, so a pub get followed straight by xcodebuild stops
with requires minimum platform version 17.0 for the iOS platform.
Installation #
This package is automatically included when you add glance_widget to your Flutter project and run on iOS.
dependencies:
glance_widget: ^1.0.0
Both CocoaPods and Swift Package Manager are supported; the same sources back each of them, so no extra step is needed either way.
Setup #
1. Create Widget Extension #
In Xcode:
- Open your iOS project (
ios/Runner.xcworkspace) - File → New → Target → Widget Extension
- Name it
GlanceWidgets - Uncheck "Include Configuration App Intent" (optional)
2. Configure App Groups #
Both the main app and widget extension need the same App Group:
- Select your main app target → Signing & Capabilities → + Capability → App Groups
- Add:
group.com.yourcompany.yourapp - Select widget extension target → repeat steps 1-2 with the same group ID
3. Configure URL Scheme #
In ios/Runner/Info.plist, add:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>glancewidget</string>
</array>
<key>CFBundleURLName</key>
<string>com.yourcompany.yourapp.widget.action</string>
</dict>
</array>
4. Implement Widget Extension #
Ready-made views for all seven templates ship with this package under
example/ios/GlanceWidgets/ — copy them into your
extension target rather than writing them by hand. The sketch below is only to
show the shape of a provider:
import WidgetKit
import SwiftUI
struct SimpleWidgetProvider: TimelineProvider {
func placeholder(in context: Context) -> SimpleWidgetEntry {
SimpleWidgetEntry(date: Date(), title: "Title", value: "--")
}
func getSnapshot(in context: Context, completion: @escaping (SimpleWidgetEntry) -> Void) {
let entry = loadFromStorage()
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleWidgetEntry>) -> Void) {
let entry = loadFromStorage()
// Use .never policy - updates only when app calls reloadTimelines
let timeline = Timeline(entries: [entry], policy: .never)
completion(timeline)
}
private func loadFromStorage() -> SimpleWidgetEntry {
let defaults = UserDefaults(suiteName: "group.com.yourcompany.yourapp")
// Load data from shared storage...
}
}
Update Strategy #
App in Foreground (Instant, No Budget!) #
When your Flutter app is in the foreground, widget updates are instant and have no budget limit:
// This triggers instant update when app is visible
await GlanceWidget.simple(
id: 'price',
title: 'Bitcoin',
value: '\$45,000',
);
App in Background (Timeline) #
When the app is in background, iOS uses timeline-based updates with a daily budget.
Server-Triggered (iOS 26+) #
For server-triggered updates without opening the app:
// Get the push token
final token = await GlanceWidget.getWidgetPushToken();
if (token != null) {
// Send to your server for APNs push
}
Server sends APNs request:
POST https://api.push.apple.com/3/device/{token}
Headers:
apns-push-type: widgets
apns-topic: com.yourcompany.yourapp.push-type.widgets
Body:
{"aps": {"content-changed": true}}
Troubleshooting #
Widget not updating? #
- Ensure App Groups are configured correctly in both targets
- Check that the App Group ID matches in your code
- Verify the widget extension is properly linked
Widget shows placeholder? #
- The widget extension can't find data in shared storage
- Verify UserDefaults suite name matches App Group ID
- Try force refreshing:
GlanceWidget.forceRefreshAll()