Open soulwawa opened 11 months ago
To update a Live Activity you need to do something in the perform function
struct RefreshIntent: LiveActivityIntent {
static var title: LocalizedStringResource = "Refresh"
static var description = IntentDescription("Refresh Description.")
func perform() async throws -> some IntentResult {
// live activity update ??
return .result()
}
}
for example you could call an API and then update the UserDefaults
Heres an example:
@available(iOS 17.0, *)
struct ReloadDataAppIntent:AppIntent{
@Parameter(title: "id")
var id:String
init() {
id = ""
}
init(id: String) {
self.id = id
}
static var title: LocalizedStringResource = "ReloadData"
func perform() async throws -> some IntentResult {
@StateObject var viewModel = ReloadDataViewModel()
let sharedDefault = UserDefaults(suiteName: "YOURGROUPNAME")!
data = await viewModel.fetchData(apiKey:"YOURAPIKEY)
sharedDefault.set(YOURDATA, forKey: "YOURKEY")
WidgetCenter.shared.reloadAllTimelines()
return .result()
}
}
Then in a button you can do
if #available(iOS 17.0, *) {
Button(intent: ReloadDataAppIntent(id: "YOUR ID")) {
Image(systemName: "arrow.clockwise")
.font(.system(size: 20, weight: .semibold, design: .rounded))
.foregroundStyle(.white)
}
.buttonStyle(PlainButtonStyle())
}
@Elliot727 Thank you reply, I don't understand maybe because I don't know the swift.
@StateObject var viewModel = ReloadDataViewModel()
let sharedDefault = UserDefaults(suiteName: "YOURGROUPNAME")!
data = await viewModel.fetchData(apiKey:"YOURAPIKEY)
sharedDefault.set(YOURDATA, forKey: "YOURKEY")
WidgetCenter.shared.reloadAllTimelines()
return .result()
Because it creates live activity with the flutter code.. It's hard to understand the code above 😭
Let me explain. Hope this helps
Creating a ViewModel with @StateObject:
@StateObject var viewModel = ReloadDataViewModel()
In SwiftUI, @StateObject
is used to create an instance of a class that survives the entire view's lifecycle. In this case, a ReloadDataViewModel
is being instantiated and managed as a state object. This is commonly used for data management in SwiftUI.
Initializing UserDefaults with a specific suite name:
let sharedDefault = UserDefaults(suiteName: "YOURGROUPNAME")!
This code initializes a UserDefaults
instance with a specified suite name. This can be useful when you want to share UserDefaults between different parts of your app or even between your app and its extensions.
Asynchronous data fetching using async/await:
data = await viewModel.fetchData(apiKey: "YOURAPIKEY")
This code calls an asynchronous function fetchData
from the ReloadDataViewModel
class, using the new async/await
syntax in Swift. It fetches data from an API and assigns it to the data
variable.
Setting data in UserDefaults:
sharedDefault.set(YOURDATA, forKey: "YOURKEY")
This line sets a value (YOURDATA
) for a specified key (YOURKEY
) in the UserDefaults instance (sharedDefault
). UserDefaults is commonly used for storing simple data persistently.
Reloading all timelines in a Widget:
WidgetCenter.shared.reloadAllTimelines()
If you are working with iOS widgets, this code triggers a reload of all the timelines associated with your app's widgets. It's useful when you want to update the content displayed in widgets dynamically.
Returning a .result() value:
return .result()
This is a generic return statement, suggesting the function returns a result. The specific meaning of .result()
depends on the context of the function and its return type.
Please replace placeholders like "YOURGROUPNAME," "YOURAPIKEY," "YOURDATA," and "YOURKEY" with your actual values as needed.
Let Me Know if you need anything else explained
Also its best to learn Swift / SwiftUI when building the iOS widgets
This is a very helpful thread, thanks all! I'm trying to go a little further and wondering if anyone has cracked this.
In the example, ReloadDataViewModel
is a Swift class. And anything run in perform
runs in a separate process from your app (and I believe it's not even guaranteed your app's process will be running at the same time).
Is there any way to invoke Dart code (like a Dart ViewModel) from the perform
function?
In the context of Flutter, it would be be great to reuse some of my request functionality that's already written in Dart than to have to recreate it in Swift.
Hi Kvenn,
To invoke Dart code from the perform
function in the Swift Live Activity, you would need to set up a communication channel between the Swift and Dart code. One approach could be to use platform channels, where the Swift code calls into the Dart code using a platform-specific method channel.
Alternatively, you could explore using a shared data store, like a database or shared preferences, where the Swift code updates the data and the Dart code observes the changes. This would allow you to reuse your existing Dart functionality without needing to directly call into it from the Swift code.
Both of these approaches would require some additional setup and integration work, but they could allow you to leverage your existing Dart code within the Live Activity implementation.
I think both of those would require the app's process to be running, which isn't necessarily guaranteed. Does that sound right?
If that's the case, you'd need to be able to launch your app's process from the Live Activity process, which I don't think is possible to do without actually launching the app (like through an intent)
Hi Kvenn,
You’re absolutely right that the solutions I mentioned earlier would require the app to be running, which isn’t guaranteed with Live Activities. However, starting with iOS 17.2, you can indeed update a Live Activity via push notifications, which opens up new possibilities.
Here's how it works:
Push Notifications for Live Activities: You can send a push notification that includes an update for the Live Activity. This means that even if your app is not running, you can still refresh the Live Activity's content.
Payload Structure: When you send a push notification to update the Live Activity, you'll include specific information in the payload that indicates which Live Activity to update and what data to refresh.
Handling Updates: In your app, you'll need to implement the handling of these push notifications to ensure that the Live Activity is updated correctly when the notification is received.
This approach allows you to leverage your existing Dart code without requiring the app to be running since the Live Activity can respond to notifications independently.
Let me know if you’d like more details on how to implement this or if there are any other aspects you’d like to discuss!
Maybe this Link might be more of what your trying to achieve ?
hi! Thanks for the great work! I want to use interactivity live activity using LiveActivityIntent.
But, I don't know how to refresh in swift code.
Can I update the live activity in swift (widget file) rather than flutter code? This is a sample code
Thank you 🙇
https://developer.apple.com/documentation/AppIntents/LiveActivityIntent