I'm developing a turn-based Messages game extension and experiencing a persistent issue on iPad where tapping on message bubbles does not reliably trigger lifecycle callbacks after the extension has been used once.
The Problem:
On iPad, after a player:
- Opens the extension by tapping a game message
- Takes their turn (plays a card)
- Sends the updated game state as a new message
- Extension collapses
When the opponent sends their response and the player taps on the new message bubble, the extension often does not open. The didSelect(_:conversation:) method is not called. The user must refresh the conversation by scrolling away and back or reopening the Messages App before tapping works again. This works perfectly on iPhone - every tap on a message bubble reliably triggers didSelect and opens the extension.
What I've Tried:
- I've implemented every lifecycle method and workaround I could find:
swiftoverride func willBecomeActive(with conversation: MSConversation) {
super.willBecomeActive(with: conversation)
if let message = conversation.selectedMessage, let url = message.url {
loadGameState(from: url, message: message, conversation: conversation)
}
}
override func didBecomeActive(with conversation: MSConversation) {
super.didBecomeActive(with: conversation)
if let message = conversation.selectedMessage, let url = message.url {
loadGameState(from: url, message: message, conversation: conversation)
}
}
override func didSelect(_ message: MSMessage, conversation: MSConversation) {
// This is NOT called on iPad when tapping message bubbles
guard let url = message.url else { return }
loadGameState(from: url, message: message, conversation: conversation)
}
override func didReceive(_ message: MSMessage, conversation: MSConversation) {
guard let url = message.url else { return }
loadGameState(from: url, message: message, conversation: conversation)
}
override func didTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
super.didTransition(to: presentationStyle)
// Attempted to reload here as well
}
I also tried:
- Observing
NSExtensionHostDidBecomeActiveandNSExtensionHostWillEnterForegroundnotifications - Forcing UI refresh in
viewDidLayoutSubviews - Checking
conversation.selectedMessagein every lifecycle method
Research: I found several Developer Forums threads from 2016 describing this exact issue:
- Thread 53167: "MSMessagesAppViewController.didSelect not called on message reselect"
- Thread 60323: "willSelectMessage and didSelectMessage don't fire"
An Apple staff member confirmed that didSelect only fires when selecting a different message, similar to UITableView selection behavior. However, on iPad, it seems like messages remain "selected" even after the extension collapses, so tapping a new message doesn't register as a new selection.
Questions:
- Is there a recommended way to detect when a user taps a message bubble on iPad, even if iOS considers a message "already selected"?
- Is there a way to programmatically deselect the current message (similar to UITableView.deselectRow) so that subsequent taps trigger didSelect?
- Are there any iPad-specific lifecycle methods or notifications I should be observing?
- Is this a known limitation of the Messages framework on iPad?
Environment:
- Xcode 16
- iOS 18 and 26
- Testing on iPad Pro (M4) and iPad Air
- iPhone works correctly on all tested devices
Any guidance would be greatly appreciated. This is blocking our App Store submission as reviewers are flagging the iPad behavior as incomplete functionality.