Group imessage send causes app to exit (didResignActive) only the first time.

I have an imessage extension app that works fine except on the first send to a group.
iOS 14.4 multiple devices 8, 8plus, 10...
Xcode 12.4

The code goes straight from the closure of 'success' to didResignActive. The app is supposed to stay active. There is no dismiss called anywhere.

If I launch the app again on the same group it works fine. Only fails if I start a new group conversation, then click on app in tray, and send is called.

note: this only happens to group sends, and only on the first time a group is created.



Code Block
thisConversation.send(message) { error in
        if let error = error {
          os_log("submitMessage(%@): initial send error: %@", log: .default, type: .debug, type, error.localizedDescription)
        } else {
          os_log("submitMessage(%@): initial send success!", log: .default, type: .debug, type)
        }
      }

Replies

Maybe you have a var not yet initialized when you create first group…

But you don't show enough code to allow proper analysis.
I don't create the group in code. the group is the list of recipients passed in to the app by imessage in the conversation object. The fact that a fresh launch of the application with only a single recipient works fine and a list of recipients fails is telling. Also, a fresh launch of the app in an existing group conversation works fine.

What code would help? I have hundreds of lines of code here. Clean build, no crash in debugger, just jumps to DidResignActive.

I've noticed that if I create a group, then send from the imessage entry a single text (can be just a character), then click on my app in tray it works fine. It's only if you click on the app in the tray w/ out first sending anything else on a group.
I do not fully understand.

then click on my app in tray it works fine. It's only if you click on the app in the tray w/ out first sending anything else on a group. 

Which tray exactly ?


When you open iMessages, click on the compose icon top right. Add two recipients. Then click on the application icon (in this case my app), below the text entry field in the application list tray( same place as the appstore icon and other apps like gif, apple pay, etc.

I was able to create a test app that reproduces this problem, with what I think is the minimal amount of code to demonstrate. Hope this invites a solution!
Code Block
//
// MessagesViewController.swift
// testGroupSend MessagesExtension
//
import UIKit
import Messages
import os
class MessagesViewController: MSMessagesAppViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
// MARK: - Conversation Handling
func composeSelectionMsg(on conversation: MSConversation, in
session: MSSession) -> MSMessage {
let layout = MSMessageTemplateLayout()
layout.caption = "caption..."
let message = MSMessage(session: session)
message.layout = layout
message.summaryText = "summary text..."
var components = URLComponents()
var queryItems = [URLQueryItem]()
queryItems.append(URLQueryItem(name: "MessageType1", value: "msgType"))
queryItems.append(URLQueryItem(name: "Encode-Name", value: "Encode-Value"))
components.queryItems = queryItems
message.url = components.url!
return message
}
func submitMessage() {
guard let conversation = activeConversation else {
os_log("submitMessage(): guard on conversation falied!", log: .default, type: .debug)
return
}
var session : MSSession
if let tSess = conversation.selectedMessage?.session {
session = tSess
os_log("submitMessage() got a session!...", log: .default, type: .debug)
} else {
os_log("###### submitMessage() did NOT get a session, creating new MSSession() #####", log: .default, type: .debug)
session = MSSession()
}
var message: MSMessage
message = composeSelectionMsg(on: conversation, in: session)
// conversation.insert(message) { error in
conversation.send(message) { error in
if let error = error {
os_log("submitMessage(): initial send error: %@", log: .default, type: .debug, error.localizedDescription)
} else {
os_log("submitMessage(): initial send success!", log: .default, type: .debug)
}
}
}
fileprivate func loadContentView() {
os_log("loadContentView()...", log: .default, type: .debug)
let childViewCtrl = ContentViewHostController()
childViewCtrl.delegate = self
childViewCtrl.view.layoutIfNeeded() // avoids snapshot warning?
if let window = self.view.window {
childViewCtrl.myWindow = window
window.rootViewController = childViewCtrl
}
}
override func willBecomeActive(with conversation: MSConversation) {
loadContentView()
}
override func didResignActive(with conversation: MSConversation) {
os_log("didResignActive()...", log: .default, type: .debug)
}
}
//
//
import SwiftUI
import Messages
import os
final class ContentViewHostController: UIHostingController<ContentView> {
weak var delegate: ContentViewHostControllerDelegate?
weak var myWindow: UIWindow?
init() {
super.init(rootView: ContentView())
rootView.submitMessage = submitMessage
}
required init?(coder: NSCoder) {
super.init(coder: coder, rootView: ContentView())
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
func submitMessage() {
os_log("ContentViewHostController::submitMessage(): submit message...", log: .default, type: .debug)
delegate?.contentViewHostControllerSubmitMessage(self)
}
}
struct ContentView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var submitMessage: (() -> Void)?
var body: some View {
VStack {
VStack {
HStack {
Button(action: { self.cancel() } ) { Image(systemName: "chevron.left") }
.padding()
Spacer()
Button(action: { self.submit() } ) {
Text("Send...")
}
.padding()
} // HStack
} // VStack
} // outside most VStack
} // body
private func cancel() {
presentationMode.wrappedValue.dismiss()
}
private func submit() {
submitMessage!()
presentationMode.wrappedValue.dismiss()
}
} // ContentView
//
//
import SwiftUI
import Messages
import os
extension MessagesViewController: ContentViewHostControllerDelegate {
// MARK: - ContenHost delegate
func contentViewHostControllerSubmitMessage(_ controller: ContentViewHostController) {
os_log("delegateSubmitMessage:...")
submitMessage()
}
}
//
//
import SwiftUI
import Messages
protocol ContentViewHostControllerDelegate: class {
func contentViewHostControllerSubmitMessage( _ controller: ContentViewHostController )
}
Just to check. Could you introduce a delay in message sending, as described here ?
https://stackoverflow.com/questions/49827017/sending-multiple-messages-in-imessage-using-swift
I modified the above code and tried this... same result...

     DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0, execute: {
      conversation.send(message) { error in
          if let error = error {
            os_log("submitMessage(): initial send error: %@", log: .default, type: .debug, error.localizedDescription)
          } else {
            os_log("submitMessage(): initial send success!", log: .default, type: .debug)
          }
        }
    })
Just an update...
I was told to file a bug report for this (which I did).

I also supplied a video which shows how to reproduce the bug.

This is the message sent back from support...

> Hi,
>
> Thank you contacting Apple Developer Technical Support (DTS).
>
> There is no workaround DTS can provide for Feedback ID #FBxxxxxx; it
> is still under investigation. Please continue to track the problem via
> the bug report.
...