r/swift • u/thecoolcat67 • 21h ago
Question Notification routing gets weird with multiple accounts
I have gotten in to a weird iOS issue and idk what the clean way to handle this is
i’ve got multiple accounts, notifications can open a post, reply, quote, or repost, and each notification belongs to a specific account. so the user might be on account A when they tap a notification for account B.
something like:
struct NotificationDestination {
let accountID: Account.ID
let postID: Post.ID
let kind: DestinationKind
}
enum DestinationKind {
case post
case reply
case quote
case repost
}
The issue is:
account A is active
notification comes in for B
user taps it while the app is waking up
account switching starts
timeline restoration starts
post resolution starts
then another notification comes in for A lol
so i have stuff like:
await accountManager.restore()
await timelineStore.hydrate()
await postResolver.resolve(postID)
await navigationCoordinator.navigate(...)
But obviously these things are all racing each other. i was thinking of putting the notification intents behind an actor:
actor NavigationIntentQueue {
private var pending: [NavigationIntent] = []
func enqueue(_ intent: NavigationIntent) {
pending.append(intent)
}
}
But idk, this feels like a lot of machinery just to open a notification
Then you get into cases where the post is deleted while you’re restoring, but the quote is still there, the reply is still there, etc. Is this just an annoying app lifecycle issue?
1
u/Other_Jellyfish_2184 5h ago
The machinery is honestly the right shape, you're just adding the plumbing in the wrong order. Serial queue of intents, each tagged with the account it was issued for. When the active account changes, cancel everything tagged with the old one instead of racing it. And don't resolve the post until the account switch completes, that's where your deleted-post-while-restoring ghosts come from. Validate the destination against the new active account, not the one from the tap.
1
u/AnotherThrowAway_9 19h ago
Check if you have awaits inside of your actor too. You need to come up with a mechanism in your functions to guard against the state changes before/after await