Hello there,
I'm playing around with the new ControlWidget controls and I'd like to start a Live Activity from on of them like they did in the WWDC Session.
Is this only possible using push notifications or is there another way around to do so locally?
Thank you.
WidgetKit
RSS for tagShow relevant, glanceable content from your app on iOS and iPadOS Home Screen and Lock Screen, macOS Desktop, Apple Watch Smart Stack and Complications, and in StandBy mode on iPhone.
Posts under WidgetKit tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hello there,
I'm playing around with the new ControlWidget controls and I'd like to know the best approach to launch a Live Activity using these.
It seems to be possible according to its WWDC session but my main question is: Is it only doable using push notifications?
Thank you.
The widget I have create for iOS 17 uses the containerBackground to display an image in the background. This works fine. But when I set the home screen to the iOS 18 tinted option the background disappears. I want the background to stay because it contains an image of that is meaningful to the user.
I use the following code:
@ViewBuilder
var body: some View {
if let memory = entry.memory, let uiImage = memory.image {
Group {
if entry.showCaption {
memoryBody(with: memory)
} else {
Color.white.opacity(0.0000000001)
}
}
.foregroundStyle(.white)
.widgetBackground(
Image(uiImage: uiImage)
.resizable()
.scaledToFill()
)
} else if let memory = entry.memory {
memoryBody(with: memory)
.widgetBackground(Color.gray)
} else {
noMemoryBody()
}
}
extension View {
func widgetBackground(_ backgroundView: some View) -> some View {
if #available(iOSApplicationExtension 17.0, *) {
return containerBackground(for: .widget) {
backgroundView
}
} else {
return background(backgroundView)
}
}
}
The Human Interface Guidelines for Live Activities provide several examples of compact presentations that have a timer counting down formatted like "3min" or "3m", similar to the timers in the Clock app. Such examples can be found in this Stack Overflow question: https://stackoverflow.com/questions/77551496/is-it-possible-to-make-an-only-minutes-1m-countdown-in-a-live-activity
A Timer initialized with init(timerInterval:pauseTime:countsDown:showsHours:) has provided a live countdown timer in widgets and live activities, but the formatting is limited. And since live activities come with limitations that prevent us from using Timers, there's no real way to implement this kind of thing ourselves.
What is Apple's official guidance for implementing this kind of timer for the compact presentation?
I try Control Widget
I check API availability like this
don't work WidgetBundleBuilder.buildBlock()
so i use ControlWidgetConfigurationBuilder.buildBlock ! but it didn't work too
what should i do ?
It's fairly well know and stated that the Apple Health / HealthKit data store is unavailable when iPhone is locked.
Since Lock Screen Widgets were introduced there's been a feature parity mismatch with Apple's own Fitness app which is able to display updating Activity Rings on the Lock Screen. Third party apps cannot do this and have to rely unlocking their device to then trigger an update. This means they often display stale and wrong Health data.
With the release of iOS 18 beta, I see no changes to this... Is there anything I've missed?
Currently for requesting the Timeline Updates on my Widget I have to just keep requesting updates as often as possible and hope that each time the iPhone might be unlocked.... This is inefficient and a waste of device resources. Even a Widget timeline reload API that let the developer say "Only call update if iPhone unlocked" would be useful.
How do I access the SwiftData ModelContainer of my app inside the widget extension?
Following the guide to add a Widget Extension I’ve added the necessary target to my project and enabled App Groups.
I’ve seen that the Backyard Birds example code offers an example how to build this, but it encapsulates the SwiftData handling in a separate app package. Therefore the example simply points to the app package. Though, in my case I don’t host my SwiftData in an external app package, but simply inside the regular app target.
So, my question is how and at which point in code do I need to access the ModelContainer?
I am trying to add more than one ControlWidget in iOS 18 and I get an error and not sure whether I am doing anything wrong or there is a bug (or maybe it's not supported by design?)
I get the following error:
encountered an error: Error Domain=com.apple.dt.deviceprocesscontrolservice Code=8 "Failed to show Widget 'check.ios18-test.intent-ext-ui' error: Error Domain=FBSOpenApplicationServiceErrorDomain Code=1 "The request to open "com.apple.springboard" failed." UserInfo={NSLocalizedFailureReason=The request was denied by service delegate (SBMainWorkspace)., BSErrorCodeDescription=RequestDenied, NSUnderlyingError=0x600000cb7060 {Error Domain=SBAvocadoDebuggingControllerErrorDomain Code=2 "Please specify the widget kind in the scheme's Environment Variables using the key '_XCWidgetKind' to be one of: "
These are the two ControlWidgets I am trying to create:
struct GetPointIntent: AppIntent {
static let title: LocalizedStringResource = "Get Point"
func perform() async throws -> some IntentResult {
return .result()
}
}
struct LeftButton: ControlWidget {
static let kind: String = "check.ios18-test.left"
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(kind: Self.kind) {
ControlWidgetButton(action: GetPointIntent()) {
Label("Plus", systemImage: "arrowshape.left")
Text("\(AppState.points)")
}
}
.displayName("Left")
.description("Left Move")
}
}
struct RightButton: ControlWidget {
static let kind: String = "check.ios18-test.right"
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(kind: Self.kind) {
ControlWidgetButton(action: GetPointIntent()) {
Label("Plus", systemImage: "arrowshape.right")
}
}
.displayName("Right")
.description("Right Move")
}
}
@main
struct intent_ext_uiBundle: WidgetBundle {
var body: some Widget {
RightButton()
LeftButton()
}
}
The app builds but upon running I get the mentioned error from Xcode
Hello, I’m upgrading my app from Core Data to SwiftData. Due to my old setup the Core Data store has an explicitly name like „Something.sqlite“, because it was defined via NSPersistentContainer(name: "Something") before switching to SwiftData.
Now my goal is to migrate the Core Data stack to SwiftData, while moving it to an App Group (for Widget support) as well as enable iCloud sync via CloudKit.
Working Migration without App Group & CloudKit
I’ve managed to get my migration running without migrating it to an App Group and CloudKit support like so:
@main
struct MyAppName: App {
let container: ModelContainer
init() {
// Legacy placement of the Core Data file.
let dataUrl = URL.applicationSupportDirectory.appending(path: "Something.sqlite")
do {
// Create SwiftData container with migration and custom URL pointing to legacy Core Data file
container = try ModelContainer(
for: Foo.self, Bar.self,
migrationPlan: MigrationPlan.self,
configurations: ModelConfiguration(url: dataUrl))
} catch {
fatalError("Failed to initialize model container.")
}
}
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(container)
}
}
How To Migrate to App Group & CloudKit?
I’ve already tried to use the ModelConfiguration with a name, but it seems to only look for a .store file and thus doesn’t copy over the Core Data contents.
let fullSchema = Schema([Foo.self, Bar.self])
let configuration = ModelConfiguration("Something", schema: fullSchema)
Can someone help me how to do this migration or point me into the right direction? I can’t find anything relating this kind of migration …
Hi, I'm developing a Live Activity Widget that shows a count down timer.
In the current solution I have a stop watch that is responsible for handling the start, stop, resume, reset function.
When the stop watch starts I have timer that calls on an updateTime function every 0.2 seconds. This works well.
The problems comes when I try to use my stop watch in the Live Activity Widget. I have a timer that updates the live activity attributes with content every 0.5 second.
// Start the activity
let activity = try? Activity.request(...
DispatchQueue.main.async {
self.logger.log("Start internal timer")
self.timer = Timer.scheduledTimer(withTimeInterval:0.5, repeats: true) { _ in
self.logger.log("Update activity widget.")
self.updateActivity()
}
}
Is this a correct approach? If not what should I use to implement a stop watch with a count down timer and a corresponding progress bar/view?
Notifying the Live Activity When Countdown is Complete:
Once the countdown timer reaches zero, how do I notify the live activity? What is the best approach to ensure the live activity updates accurately and promptly?
Handling App Suspension in the Background:
When my app is in the background, it gets suspended. Should I set up a job queue on the backend to send an update push notification when the timer ends? Is there a more efficient way to handle this?
Ensuring Timer Accuracy:
Since this feature deals with time, I am concerned about the accuracy of the timer. How can I ensure the countdown timer remains accurate even when the app is not in the foreground?
Any answers, insights, or guidance on these issues would be greatly appreciated. Thank you in advance for your help!
I have a basic Widget with a button to toggle the home lights, the buttons triggers the following AppIntention:
import WidgetKit
import AppIntents
struct ConfigurationAppIntent: WidgetConfigurationIntent {
static var title: LocalizedStringResource = "Bulb state"
static var description = IntentDescription("This is an example widget.")
}
struct ToggleStateIntent: AppIntent {
static var title: LocalizedStringResource = "Toggle light state"
init(){
}
func perform() async throws -> some IntentResult {
await WizClient.shared.toggleState()
return .result()
}
}
The problem is that I must be running the app with xcode (in my phone, not simulator) to work fine, when I stop xcode the button must be pressed two times to trigger the AppIntention.
The toggle function works well on the app with a toggle component.
Here is the widget:
import WidgetKit
import SwiftUI
struct Provider: AppIntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), configuration: ConfigurationAppIntent())
}
func snapshot(for configuration: ConfigurationAppIntent, in context: Context) async -> SimpleEntry {
SimpleEntry(date: Date(), configuration: configuration)
}
func timeline(for configuration: ConfigurationAppIntent, in context: Context) async -> Timeline<SimpleEntry> {
let timeline = Timeline(entries: [SimpleEntry(date: Date(), configuration: configuration)], policy: .atEnd)
return timeline
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationAppIntent
}
struct BulbActionsEntryView : View {
var entry: Provider.Entry
var body: some View {
HStack {
Button(intent: ToggleStateIntent()){
Text("Toggle")
}
}
.padding(.vertical)
}
}
struct BulbActions: Widget {
let kind: String = "BulbActions"
var body: some WidgetConfiguration {
AppIntentConfiguration(kind: kind, intent: ConfigurationAppIntent.self, provider: Provider()) { entry in
BulbActionsEntryView(entry: entry)
.containerBackground(.fill.tertiary, for: .widget)
}
}
}
extension ConfigurationAppIntent {
fileprivate static var test: ConfigurationAppIntent {
let intent = ConfigurationAppIntent()
print("Intent -> \(intent)")
return intent
}
}
#Preview(as: .systemSmall) {
BulbActions()
} timeline: {
SimpleEntry(date: .now, configuration: .test)
}
Our app is a time reporting service with various functions around that. The user checks in at work, checks out when they go home.
We thought it'd be useful to provide a live activity to show how long they have worked for.
There is also a couple of other cool things we could do that users would love, but i couldn't find definitive answers to the questions below.
1.
We have a geofence-based function that checks the user in when they for example arrive at work, and check them out when they go home, so that they don't have to open the app.
However, this means that we will need to start and end the live activity from within a geofence trigger. Is this possible?
2.
It seems that the maximum time for a live activity is 8 hours? Sometimes people work for longer... How would we solve this? i would be fine with 12 since it would solve most cases.
Is it possible somehow to go beyond 8 hours up to 12?
If not, is there a callback that "8 hours are up!" so that i could do a final update on the live activity from a counter to "you started working at 09:04"
3.
I have seen that some live activities have buttons. It would be neat if the user can check out via a button on the live activity. However, since we take location and call our servers when checking out, we
need to be able to use both the locationmanager and make a network call from the live activity. Is this possible?
Thanks in advance, Cheers
I am trying to bring my iOS App to native macOS. I am using exactly the same TimelineProvider and widgets (the ones not supported on macOS surrounded by #if(os)). Running the whole app or just the WidgetExtension on iOS works perfectly fine. Running the mac app works perfectly fine apart from missing Widgets.
When running the WidgetExtension on My Mac, the WidgetKit Simulator opens and only presents Failed to load widget. The operation couldn't be completed. (WidgetKit_Simulator.WidgetDocument.Error error 4.) The code compiles fine without any warnings, only a file path is printed into the console. file:///Users/myName/Library/Developer/Xcode/DerivedData/MyAppName-dfsiuexplidieybwvbkqofchxirp/Build/Products/Debug/MyApp.app/Contents/PlugIns/MyAppNameWidgetExtensionExtension.appex/
Shortly after I get a log entry Logging Error: Failed to initialize logging system. Log messages may be missing. If this issue persists, try setting IDEPreferLogStreaming=YES in the active scheme actions environment variables.
I am not sure which further Informationen I can give to solve my problem. Destinations on main App and Widget Extension is both set to Mac (no suffix). The mac is running 14.4.1 and Xcode 15.3.
I am really thankful for any assistance you can give me to fix this problem. Thanks
I have a bundled application that contains a widget extension. On launching the application once the widget appears in the widget gallery, However, I have observed that If my widget extension is not sandboxed, the widget fails to show in the widget gallery. Is this expected? I am using the same xcode project and just that AppSandbox capability for the widget extension target is causing this. Can someone please explain why is this happening?
I've been developing widgets for an app and have been making frequent changes to the views to try different things out. Maybe I should be using previews for this, but I've been testing on simulators and my iPhone. I've found that after some point, my code all of a sudden stops affecting the widgets on my physical iPhone and on every simulator device, even after restarts of my laptop, wipes of the simulators, etc. And I'm not able to continue development until the next day. It seems like I'm hitting the hard limit for timeline requests in a day, but I feel like that shouldn't apply to simulators or should be refreshed when reinstalling for development?
Thanks.
I'm currently working with complication using widgetkit for watchOS.
When I select complication from Watch app in iPhone, The complication does not show content. In complication gallery, untitled complication is selecting. But when I select complication from watch, it's OK.
This bug occurs in both real device and simulator. But it happen in some pair.
Example:
watch ultra (os 10.4) pair with iPhone 14 pro (os 17.0): NG
watch ultra (os 10.4) pair with iPhone 14 pro (os 16.1): NG
watch ultra (os 10.0) pair with iPhone 14 pro (os 17.0): OK
I tried create simple project to check this bug. But this bug still occurs
This is sample project: Github
Environment:
Xcode 15.3.0.
MacOS 14.4.1 (23E224)
Depl. Target: iOS 17.2
Supported Destinations: iPhone
Notes: Using SwiftData. Shared code in the Persistency library.
Hello everyone,
I am writing here after really trying everything I can to understand what is going on.
I have a widget bundle composed by two different widgets, defined as following:
import WidgetKit
import SwiftUI
import SwiftData
@main
struct MyWidgetBundle: WidgetBundle {
@WidgetBundleBuilder
var body: some Widget {
MyWidget()
MylMediumWidget()
}
}
They have 2 different providers (since they need different data).
The are then defined as following:
import SwiftUI
import WidgetKit
import Persistency
import SwiftData
struct MyMediumWidget: Widget {
let kind: String = "MyStatus"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: MyEntryProvider()) { entry in
MyMediumWidgetView(entry: entry)
.containerBackground(Color.Theme.background, for: .widget)
}
.supportedFamilies([.systemMedium, .systemLarge])
.configurationDisplayName("My Reminder Medium")
.description("Bla bla bla")
}
}
And
import WidgetKit
import SwiftUI
import Persistency
struct MyWidget: Widget {
let kind: String = "MyStatus"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: SmallEntryProvider()) { entry in
MyWidgetGroup(entry: entry)
.containerBackground(Color.Theme.background, for: .widget)
}
.supportedFamilies([.systemSmall, .accessoryCircular])
.configurationDisplayName("My Reminder Small")
.description("Bla bla 2")
}
}
struct ActiveMealWidgetGroup: View {
var entry: SmallEntryProvider.Entry
@Environment(\.widgetFamily) var family
var body: some View {
switch family {
case .systemSmall:
MySmallWidgetView(entry: entry)
case .accessoryCircular:
MyAcessoryCircularWidgetView(entry: entry)
default:
Text("Unsupported size")
}
}
}
Note: They belong to 1 single Widget Extension for iOS.
For some reason I have VERY strange behaviors in widgets with the following code.
Example:
When I insert the medium size, it is randomly removed from the home screen. For example, I add the small and the medium. After 3h, the medium is gone.
If I try to add the widgets in mac os (readying from phone, the app is only for iOS), only the small appears. No medium and large are shown.
If I try to compile the widget scheme selecting systemLarge in the xcode argument, I have an error saying: "Request widget family (systemLarge) is not supported by this widget kind (MyStatus)" UserInfo={NSLocalizedDescription=Request widget family (systemLarge) is not supported by this widget kind (MyStatus)}}
What is going on? Seems my widgets are really wrongly configured, but I can't see where the issue can be.
Hope someone can help me.
Best Regards
There seems to be a long running issue with WidgetKit where some users don't see the widget when trying to add to their Home Screen. (even after opening the app for the first time).
I have been able to reproduce myself intermittently, and typically restarting the phone or re-installing the app fixes the problem. However, some of my users have encountered this and end up requesting refunds because they think the app is broken.
Has anybody else experienced this issue?
Would be great to get this bug resolved as it's frustrating for users.
I've reached a point where I can no longer make any progress diagnosing the issues that have popped up with Apple Watch development support. To hopefully help draw attention and focus to the severity of this problem, I'm gathering all related threads into this single thread.
Summary of problems
There are several, possibly related, issues at play:
Xcode is not discovering Apple Watches. This means it's not possible to deploy apps to Apple Watches that aren't already provisioned with Xcode. I've confirmed this behavior with a watch running watchOS 10.0.
The logging profile for watchOS has expired. It's no longer possible to pull logs via Console from Apple Watches.
AppIntent-based complications on watchOS 10.5 no longer load, staying stuck in a "placeholder" state. This can be reproduced with the Backyard Birds demo app.
It's no longer possible to debug widget extensions on Apple Watch hardware.
Feedback submitted
FB13758427: No longer able to connect to Apple Watch from Xcode
I was attempting to test another regression related to AppIntents no longer working on watchOS 10.5. To confirm the behavior had regressed since earlier versions of watchOS, I set up one of my older Apple Watches that is still running watchOS 10.0.
After wiping the watch and repairing it with one of my test devices (iPhone 11 Pro, iOS 17.4.1), I’m unable to get the Apple Watch to appear in Xcode’s Devices & Simulators manager. The phone is connected via USB cable, and the phone appears as a Connected phone, but the watch does not appear. My Apple Watch Ultra that I use as my daily driver does appear as a remote device (the globe icon is next to it), but the Apple Watch 10.0 does not appear.
Details about the older watch:
Version: 10.0 21R5341c
Model: A2478
Not being able to test on other Apple Watches is severely limiting my ability to isolate and confirm the regression in AppIntent support that can be reproduced in the Backyard Birds demo app.
Note that the 10.0 watch does actually appear in the Console app, but with a warning sign next to it. The 10.0 watch also appears twice. Clicking the warning sign does not reveal any information about why the warning is appearing, but after ~5 seconds I do get the following error in Console.app: “The user has not responded to the pairing request on 'Headless’ Respond to the Trust prompt on the device.” There is no trust prompt on the device.
FB13756074: WatchOS logging profile is no longer valid
https://developer.apple.com/bug-reporting/profiles-and-logs/?platform=watchos is no longer valid. See attached error that occurs when attempting to install the profile onto my Apple Watch Ultra.
It seems that without this I’m unable to get any logs off of my Apple Watch, which is making testing/development quite difficult.
FB13758450: AppIntent-based widgets no longer render on watchOS 10.5
AppIntent-based complications no longer get beyond a placeholder state on watchOS. This can be reproduced with the Backyard Birds demo app, which uses AppIntent-based widget configurations for the watchOS complications. AppIntent-based complications did appear to work in previous versions of watchOS 10, but I’m unable to confirm this with a 10.0 Watch I have due to FB13758427.
To reproduce
deploy the attached unmodified Backyard Birds app to a watch running watchOS 10.5.
add a Backyard Birds complication to a watch face.
Expected behavior: the widget shows live data
Actual behavior: the complication never leaves a placeholder state. See the attached screenshot for the state the widget is stuck in.
FB13758490: PacketLogger no longer logs packets
PacketLogger used to log BTLE packets as they were received and transmitted on a macOS machine. Since updating to 14.5 Beta (23F5064f) however, PacketLogger no longer logs packets on macOS at all. Upon starting a new session, the interface remains empty.
PacketLogger is still able to log packets from a connected iOS device.
Related threads
Apple Watch cannot reconnect
WatchOS Sysdiagnose Profile is no longer
XCode 15 can't run on iOS 17 devices. Previous preparation error: An error occurred while communicating with a remote process.. The connection was invalidated.