Hello,
I have an app in AppStore "Counter Widget". https://apps.apple.com/app/id1522170621
It allows you to add a widget to your homescreen/lockscreen to count anything.
Everything works fine except for one scenario. iOS 18+
I create 2 or more widgets for one counter. For example, medium and small widgets.
I click on the widget button to increase or decrease the value.
The button in the widget uses Button(intent: AppIntent) to update the value and calls WidgetCenter.shared.reloadAllTimelines() to update the second widget for the same counter.
For iOS 18 in this particular scenario, you don't even have to call the WidgetCenter.shared.reloadAllTimelines(). iOS already knows that there is a widget with the same INIntent settings and will update it itself.
Both widgets are updated and show the new value. Everything is correct.
Now on the homescreen I open the widget configuration for one of the widgets to change the INIntent for the widget. For example, i change the background to wallpaper. This is just a skin for the widget, and the widget is associated with the same counter value as before.
As in (2), I click the widget button to increase or decrease the value.
But now only one widget is updated. iOS ignores my call to WidgetCenter.shared.reloadAllTimelines() and does not update the second widget connected to the same counter.
As I found, iOS, when I call WidgetCenter.shared.reloadAllTimelines() from the widget itself, updates other widgets only if INIntent is absolutely equal for them.
Overriding isEqual for them did not help. That is, I cannot specify which fields from my INIntent can be ignored during such an update and consider that widgets are equal and need to be updated. Obviously iOS make this compare outside my code.
The main problem is that when the user adds a widget to the lock screen and increases and decreases the value there. After that, he opens the home screen and the widget there is not synchronized with the value from the widget on the lock screen.
How to solve this problem?
Widgets & Live Activities
RSS for tagDiscuss how to manage and implement Widgets & Live Activities.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi everyone,
I’m working on implementing Live Activities in my app, and I’ve encountered an issue where the Live Activity updates work intermittently when the app is in the background. Sometimes they update correctly, but at other times, they don’t update at all, even though they should be running in the background.
However, when the app is brought to the foreground, the updates happen correctly.
A few things I’ve checked:
The app is using ActivityKit to update the Live Activity with Activity.update().
I’ve enabled the necessary background modes in the Capabilities section.
Is there a possibility that I’m hitting the system budget limit while experiencing this issue? If this is a limitation, how can I avoid it or manage this situation?
Has anyone else faced this issue? Any advice or potential solutions would be greatly appreciated!
Thank you!
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Tags:
Swift
SwiftUI
WidgetKit
ActivityKit
I've been working on a new application and beta testing with TestFlight. When iOS 18.3 came out, my widgets stopped working due to using too much memory. I've been trying to debug for a while now, but not making much progress. Now that iOS 18.4 is out, I noticed the widgets are working again.
I'm wondering if there was some change made in iOS 18.3 that was rolled back in iOS 18.4 that I'm not seeing in the iOS Release Notes etc? I haven't seen much in the Developer Forums, either.
My concern is that perhaps Apple decided to make the 30MB Widget memory limit a "hard" limit, but then rolled it back, perhaps temporarily, so I'd like some clarity on the situation if possible.
Otherwise, I did notice that it seemed as if all of my widgets were loaded at once, even if only one widget was installed, this boosting the memory usage significantly. If so, that might indicate that a bug was fixed in the Widget Provider system?
In any case, I'd appreciate any information or advice on this.
Thanks!
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Live Activity Start Token not generating after certain days of usage. We have implemented Live Activity feature where the initial activity is launched by our backend. But to start that first live activity I need push to start token which is generating for few days but all of sudden after certain days it stops generating. Currently we are in development phase so we test it on multiple devices and multiple time we are doing install and uninstall.
STEPS TO REPRODUCE
Install the app
Start token gets generated which is sent to our server
After certain duration server sends the first live activity using that token
user opens the app then we receive the updated token and send that token to server
server uses that updated token to further update the live activity.
All this works fine. But after a week of usage we are observing that we stop getting start token from APNS. Not sure where exactly the thing is breaking. We have tried with different devices and different bundle identifiers but behaviour is same for all.
func generateStartToken() {
Task.detached { [weak self] in
guard let self else { return }
await self.observeActivityPushTokenAndState()
for await data in ActivityKit.Activity<LiveActivityAttribute>.pushToStartTokenUpdates {
let token = data.map { String(format: "%02x", $0) }.joined()
print("Activity Start token: ", token)
}
}
}
func observeActivityPushTokenAndState() {
Task.detached {
for await activity in ActivityKit.Activity<LiveActivityAttribute>.activityUpdates {
Task {
for await tokenData in activity.pushTokenUpdates {
let updatedToken = tokenData.map { String(format: "%02x", $0) }.joined()
print("Activity Update token: ", updatedToken)
}
}
Task {
for await content in activity.contentUpdates {
let updatedContent = content.state
print("Activity Updated: ", updatedContent)
}
}
}
}
}
I am building a widget with configurable options (dynamic option) where the options are pull from api (ultimately the options are return from a server, but during my development, the response is constructed on the fly from locally).
Right now, I am able to display the widget and able to pull out the widget configuration screen where I can choose my config option . I am constantly having an issue where the loading the available options when selected a particular option (e.g. Category) and display them on the UI. Sometime, when I tap on the option "Category" and the loading indicator keeps spinning for while before it can populate the list of topics (return from methods in NewsCategoryQuery struct via fetchCategoriesFromAPI ). Notice that I already made my fetchCategoriesFromAPI call to return the result on the fly and however the widget configuration UI stills take a very long time to display the result. Even worst, the loading (loading indicator keep spinning) sometime will just kill itself after a while and my guess there are some time threshold where the widget extension or app intent is allow to run, not sure on this?
My questions:
How can I improve the loading time to populate the dynamic options in widget configuration via App Intent
Here is my sample code for my current setup
struct NewsFeedConfigurationIntent: AppIntent, WidgetConfigurationIntent {
static let title: LocalizedStringResource = "Configure News Topic Options"
static let description = IntentDescription("Select a topic for your news.")
@Parameter(title: "Category", default: nil)
var category: NewsCategory?
}
struct NewsCategory: AppEntity, Identifiable {
let id: String
let code: String
let name: String
static let typeDisplayRepresentation: TypeDisplayRepresentation = "News Topic"
static let defaultQuery = NewsCategoryQuery()
var displayRepresentation: DisplayRepresentation {
DisplayRepresentation(title: LocalizedStringResource(stringLiteral: name))
}
}
struct NewsCategoryQuery: EntityQuery {
func entities(for identifiers: [NewsCategory.ID]) async throws -> [NewsCategory] {
let categories = fetchCategoriesFromAPI()
return categories.filter { identifiers.contains($0.id) }
}
func suggestedEntities() async throws -> [NewsCategory] {
fetchCategoriesFromAPI()
}
}
func fetchCategoriesFromAPI() -> [NewsCategory] {
let list = [
"TopicA",
"TopicB",
"TopicC",
.......
]
return list.map { item in
NewsCategory(id: item, code: item, name: item.capitalized)
}
}
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Tags:
WidgetKit
Intents
App Intents
I would like to add a Live Activity to my app, but unfortunately I always get an error message. When I go into the Identifiers via the Developer Portal and look at my app, there is no Activity Kit or Live Activity in the Capabilites that I could activate. In XCode I don't see the option for Signing & Capabilities either... Can anyone help me how to add this correctly? Thanks in advance!
I'm developing a widget with WidgetKit, and I'm having a problem: I need to click on an image, and when I click it triggers a network request, the image automatically rotates clockwise, and when the network ends, the image automatically stops rotating. How to do that?
My current idea is to click on the image and await the call to the network request. Should Toggle be used for the control corresponding to the picture? Because Toggle has two states. Then there is how to do image rotation, did not find support API.
Device: iPhone 16 Pro
iOS version: 18.3.2
The calendar widget (on home screen) is displaying "No more events today" even though there is an appointment scheduled later in the evening on the same day.
I have looked through all the settings and nothing seems to work. How do I get it to display events that are on the calendar for rest of the day today.
It does correctly display events that are upcoming tomorrow and next week.
Thanks,
-Harry
Hello everyone,
I am currently developing a media playback app and want to achieve the following functionality:
Display multiple media contents in the Now Playing control center, instead of just showing the currently playing one.
Allow users to select and switch between different contents, such as videos, music, etc., from the control center.
However, I have encountered some issues:
Although I have integrated the Now Playing control center, it only displays the current media being played.
I would like to display multiple selectable media contents (such as a video list, music list, etc.) in the control center, similar to what is done by some media player apps, and allow users to switch between them.
I’ve tried the following methods:
Using MPNowPlayingInfoCenter to update the current playing media information.
Attempting to set MPNowPlayingInfoPropertyPlaybackQueueCount to show multiple items in the queue, but it doesn’t seem to work.
Can anyone provide guidance on how to display multiple media contents in the Now Playing control center? Any experienced developers who could share their insights or suggestions would be greatly appreciated!
Thank you very much for your help and feedback!
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Hello,
We are using the Firebase Admin SDK (firebase-admin framework) to send push notifications via Firebase Cloud Messaging (FCM) for Live Activity updates in our iOS app.
With the introduction of iOS 18, a new key "input-push-token": 1 has been added to the Live Activities push payload structure.
1) Can this new key ("input-push-token": 1) be used when sending payloads via FCM?
We noticed that FCM is still using the push update format introduced in iOS 17.2. Will FCM be updated to support the new push structure introduced with iOS 18? Or is the "input-push-token" feature only available when sending notifications via direct APNs?
2) We are concerned about the expiration of the Live Activity start push token.
If a user doesn't open the app for a long time, the token may expire, and this could result in failed updates. That’s why we are looking into the new "input-push-token" behavior in iOS 18.
Do you have any recommendations on how to manage or prevent token expiration?
Is there any official guidance on the lifespan of the Live Activity push tokens?
Will FCM support the delivery of start/update/end Live Activity actions even when the app is completely terminated?
We would highly appreciate any official clarification or roadmap regarding this. It would help us determine whether we should wait for FCM support or switch to sending notifications directly via APNs.
Thank you for your help!
Issue Report
1.Multiple instances of the same widget from one app were added,
but only one fails to display while others work normally.
2.Sometimes the widget displays blank on iOS 18.3.2
Technical Context
Occurs intermittently
Specific to iOS version 18.3.2
Widget content fails to render
My widget requests server data updates in getTimeline to refresh information. But if the server API returns an error and I don't execute the completion callback, will this cause any problems?
Hi everyone,
I'm working with Live Activities using the ActivityKit(Activity), and I'm trying to find a way to detect when a user manually dismisses a Live Activity by swiping it away — either from the Lock Screen or the Dynamic Island.
Currently, when a Live Activity ends, the activityState changes to .dismissed, which is defined as:
/// The Live Activity ended and is no longer visible because a person or the system removed it.
case dismissed
This doesn’t allow me to determine whether the dismissal was triggered by the user or by the system.
Is there any way — either through ActivityState, notifications, or another approach — to distinguish if a Live Activity was manually dismissed by the user vs. ended by the system?
Thanks in advance!
Hello,
I'm working with Live Activities and noticed that sometimes an activity transitions to .dismissed, even though the user hasn't manually swiped it away and system conditions appear to be completely normal — such as:
The activity is still within its intended 8-hour lifetime
The battery level is high
The app is active or recently active
The activity is lightweight (not using frequent updates)
According to the ActivityKit documentation:
/// The Live Activity ended and is no longer visible because a person or the system removed it.
case dismissed
This doesn’t clarify why the system would dismiss an activity when all conditions seem fine.
Additional context:
When reviewing system logs via Console.app, we’re seeing messages such as:
liveactivitiesd Removing activity from replicator: 381F3DDC-585B-4021-B075-548606F543DA for relationship IDs: [C7AB9C2A-49DD-43FC-BB58-D768ECF9D354]
This suggests that the system is actively removing the activity, but there’s no API or reason provided that helps us understand why this is happening.
Questions:
What are the system-level triggers that could cause a Live Activity to be dismissed under normal conditions?
Is there a known set of heuristics (e.g., memory pressure, resource constraints) that might apply?
Is there a way to distinguish between system-triggered dismissal and user-initiated swipe-to-dismiss?
Any best practices to reduce the likelihood of unexpected system removal?
This is especially important for our use case, where users rely on Live Activities to view real-time flight and boarding information — and losing the activity unexpectedly negatively affects user experience.
Thanks in advance for any insight!
I have an objective-c watch app and have added a swift widget style compilation to it and am having problems. The complication works fine but the name in the iPhone watch app complication picker stubbornly remains as the watchkit app name despite me trying various ways of changing it.
Here are the various CF bundle name and display name values I am using:
phone app values
CFBundleIdentifier - com.Distribution-Systems-Associates.Tennis-Watch-v1
CFBundleName - $(PRODUCT_NAME)
CFBundleDisplayName - Tennis Scorekeeper
watchkit app
CFBundleIdentifier - com.Distribution-Systems-Associates.Tennis-Watch-v1.watchkitapp
CFBundleName - Tennis Scorekeeper
CFBundleDisplayName - Tennis Scorekeeper
WatchKit extension
CFBundleIdentifier - com.Distribution-Systems-Associates.Tennis-Watch-v1.watchkitapp.watchkitextension
CFBundleName - Tennis Scorekeeper
CFBundleDisplayName - Tennis Scorekeeper
__Watchkit complication __
CFBundleIdentifier - com.Distribution-Systems-Associates.Tennis-Watch-v1.watchkitapp.watchkitextension.Tennis-Watch-V1-Complication
Changing the values in the complication doesn't seem to matter. Every other name in both my iPhone and watch apps are as expected.
ChatGPT suggested that I try adding a localized name in the watchkit app but that didn't seem to do much of anything useful. I have run this though Chat quite a bit to see if I could get any accidental insights that way and while it has been interesting, it has also been not terribly helpful.
I didn't post any of the complication code because that seems to be fine. However, I can do that if needed. The complication works as intended (starts the app). The various names everywhere else show up as intended. It's just that this one name refuses to be overridden. Thoughts?
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Tags:
WatchKit
Swift
Objective-C
WidgetKit
Trying to start a live activity without showing anything, and update its UI while app is being terminated. However, we found very inconsistent behavior - sometimes it shows sometimes not - could you help figure out the cause?
Is there any way to obtain the ControlWidget installed by user, I use WidgetCenter.shared.getCurrentConfigurations cannot work
Hello,
I am trying to get the elements from my SwiftData databse in the configuration for my widget.
The SwiftData model is the following one:
@Model
class CountdownEvent {
@Attribute(.unique) var id: UUID
var title: String
var date: Date
@Attribute(.externalStorage) var image: Data
init(id: UUID, title: String, date: Date, image: Data) {
self.id = id
self.title = title
self.date = date
self.image = image
}
}
And, so far, I have tried the following thing:
AppIntent.swift
struct ConfigurationAppIntent: WidgetConfigurationIntent {
static var title: LocalizedStringResource { "Configuration" }
static var description: IntentDescription { "This is an example widget." }
// An example configurable parameter.
@Parameter(title: "Countdown")
var countdown: CountdownEntity?
}
Countdowns.swift, this is the file with the widget view
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> {
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate, configuration: configuration)
entries.append(entry)
}
return Timeline(entries: entries, policy: .atEnd)
}
// func relevances() async -> WidgetRelevances<ConfigurationAppIntent> {
// // Generate a list containing the contexts this widget is relevant in.
// }
}
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationAppIntent
}
struct CountdownsEntryView : View {
var entry: Provider.Entry
var body: some View {
VStack {
Text("Time:")
Text(entry.date, style: .time)
Text("Title:")
Text(entry.configuration.countdown?.title ?? "Default")
}
}
}
struct Countdowns: Widget {
let kind: String = "Countdowns"
var body: some WidgetConfiguration {
AppIntentConfiguration(kind: kind, intent: ConfigurationAppIntent.self, provider: Provider()) { entry in
CountdownsEntryView(entry: entry)
.containerBackground(.fill.tertiary, for: .widget)
}
}
}
CountdownEntity.swift, the file for the AppEntity and EntityQuery structs
struct CountdownEntity: AppEntity, Identifiable {
var id: UUID
var title: String
var date: Date
var image: Data
var displayRepresentation: DisplayRepresentation {
DisplayRepresentation(title: "\(title)")
}
static var defaultQuery = CountdownQuery()
static var typeDisplayRepresentation: TypeDisplayRepresentation = "Countdown"
init(id: UUID, title: String, date: Date, image: Data) {
self.id = id
self.title = title
self.date = date
self.image = image
}
init(id: UUID, title: String, date: Date) {
self.id = id
self.title = title
self.date = date
self.image = Data()
}
init(countdown: CountdownEvent) {
self.id = countdown.id
self.title = countdown.title
self.date = countdown.date
self.image = countdown.image
}
}
struct CountdownQuery: EntityQuery {
typealias Entity = CountdownEntity
static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "Countdown Event")
static var defaultQuery = CountdownQuery()
@Environment(\.modelContext) private var modelContext // Warning here: Stored property '_modelContext' of 'Sendable'-conforming struct 'CountdownQuery' has non-sendable type 'Environment<ModelContext>'; this is an error in the Swift 6 language mode
func entities(for identifiers: [UUID]) async throws -> [CountdownEntity] {
let countdownEvents = getAllEvents(modelContext: modelContext)
return countdownEvents.map { event in
return CountdownEntity(id: event.id, title: event.title, date: event.date, image: event.image)
}
}
func suggestedEntities() async throws -> [CountdownEntity] {
// Return some suggested entities or an empty array
return []
}
}
CountdownsManager.swift, this one just has the function that gets the array of countdowns
func getAllEvents(modelContext: ModelContext) -> [CountdownEvent] {
let descriptor = FetchDescriptor<CountdownEvent>()
do {
let allEvents = try modelContext.fetch(descriptor)
return allEvents
}
catch {
print("Error fetching events: \(error)")
return []
}
}
I have installed it in my phone and when I try to edit the widget, it doesn't show me any of the elements I have created in the app, just a loading dropdown for half a second:
What am I missing here?
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Tags:
SwiftUI
WidgetKit
App Intents
SwiftData
I found the live activity process cannot write to the app group and FileManger, can only read the app group.
When I write using FileManager in a live activity process, the console prompts me with a permission error.
When I write using UserDefault(suit:) in the live activity process, I read a null value in the main app.
Is this the case for real-time event design? I haven’t seen any documentation mentioning this.
Does anyone know, thank you very much.
I tested it on the app I work with and others I use and the notification message is not appearing when using sleep mode
Iphone: 13 mini
IOS: 18.4.1