My question is about subscribing to multiple Live Activities of the same type (the same ActivityAttributes) and then handle them separately when using push to start one of them.
I want the user to be able to follow multiple football matches. However, when I listen to pushToStartTokenUpdates
sequence, I always get the same token, even when I call the function multiple times.
How am I supposed to have the user start multiple future activities, and then push to start them separately?
I can store the matchId locally, and only pass the update when the received id from the push matches the stored one, but is this really the best way to do this? Am I missing something or have Apple really not thought about this?
Edit:
Here is a simplification of what I mean by the start token only being decided by the type, not the matchId. I do not know any other way of retrieving the start token, but I have probably missed something? Run the code in AppDelegate to test, but the result will be the same token being printed twice.
import ActivityKit
import SwiftUI
struct FootballActivityAttributes: ActivityAttributes {
var eventId: String
var homeTeam: String
var awayTeam: String
public struct ContentState: Codable, Hashable {
var homeScore: Int
var awayScore: Int
}
}
func getPushToStartToken(eventID: String) async throws -> String? {
print("Running Live Activity: Fetching pushToStartToken for event \(eventID)...")
for await data in Activity<FootballActivityAttributes>.pushToStartTokenUpdates {
let token = data.map {String(format: "%02x", $0)}.joined()
print("Live Activity: Saved pushToStartToken for event \(eventID): \(token)")
return token
}
print("Live Activity: Found no token")
return nil
}
for eventId in ["12345", "67890"] {
Task {
try await getPushToStartToken(eventID: eventId)
}
}
My question is about subscribing to multiple Live Activities of the same type (the same ActivityAttributes) and then handle them separately when using push to start one of them.
I want the user to be able to follow multiple football matches. However, when I listen to pushToStartTokenUpdates
sequence, I always get the same token, even when I call the function multiple times.
How am I supposed to have the user start multiple future activities, and then push to start them separately?
I can store the matchId locally, and only pass the update when the received id from the push matches the stored one, but is this really the best way to do this? Am I missing something or have Apple really not thought about this?
Edit:
Here is a simplification of what I mean by the start token only being decided by the type, not the matchId. I do not know any other way of retrieving the start token, but I have probably missed something? Run the code in AppDelegate to test, but the result will be the same token being printed twice.
import ActivityKit
import SwiftUI
struct FootballActivityAttributes: ActivityAttributes {
var eventId: String
var homeTeam: String
var awayTeam: String
public struct ContentState: Codable, Hashable {
var homeScore: Int
var awayScore: Int
}
}
func getPushToStartToken(eventID: String) async throws -> String? {
print("Running Live Activity: Fetching pushToStartToken for event \(eventID)...")
for await data in Activity<FootballActivityAttributes>.pushToStartTokenUpdates {
let token = data.map {String(format: "%02x", $0)}.joined()
print("Live Activity: Saved pushToStartToken for event \(eventID): \(token)")
return token
}
print("Live Activity: Found no token")
return nil
}
for eventId in ["12345", "67890"] {
Task {
try await getPushToStartToken(eventID: eventId)
}
}
Share
edited Mar 10 at 8:58
Paulw11
115k15 gold badges171 silver badges209 bronze badges
Recognized by Mobile Development Collective
asked Mar 6 at 19:35
MatiasVianMatiasVian
114 bronze badges
5
|
1 Answer
Reset to default 0There is only one active pushToStartToken
at any point for a given Activity<Attributes>
type, because that token is just used to start new activities. Each active Activity
has its own update token that you use to send updates for that activity.
Broadly, this is what your app needs to do:
- Observe the
pushStartTokenUpdates
sequence forActivity<FootballActivityAttributes>
- Send the token to your server when it is updated
- Maintain a list of matches that your user is interested in on your server
- When a match they are interested in starts, send a start activity push to the
pushStartToken
. The payload for this activity must include the relevanteventId
,homeTeam
andawayTeam
properties - Your app also needs to observe the
Activity<FootballActivityAttributes>.activityUpdates
async sequence- When a new activity is started, it will be delivered via this sequence.
- I suggest keeping a dictionary of live activities, keyed by
eventId
, that way you can easily detect new live activities. - Observe the
pushTokenUpdates
sequence for this activity and send it to your server along with theeventId
from the activity's attributes.
for await activity in Activity<FootballActivityAttributes>.activityUpdates {
Task {
for await tokenData in activity.pushTokenUpdates {
let token = tokenData.map {String(format: "%02x", $0)}.joined()
print("Push token: \(token)")
// Send token to your server along with user id and activity.attributes.eventId
}
}
}
- Your server can now send
update
push notifications to this activity-specific token - At the end of the match you can send an
end
notification to the activity-specific token.
matchId
or similar. You should edit your question to show the relevant code. – Paulw11 Commented Mar 7 at 11:13pushToStartToken
but each activity has its own update push token – Paulw11 Commented Mar 10 at 10:54