INSendMessageIntent suggestions always show "1 person", even for multiple recipients

I'm trying to donate an INSendMessageIntent for multiple recipients in a group. No matter what I do, the share sheet shows "1 Person" and a maximum of 1 profile image.

How can I get it to show the correct number of people, and all of the profile images I set?

Example screenshot: i.stack.imgur.com/VRf5i.png
Sample code follows.
  • Click "Donate Group Without Images" => share sheet suggestion shows 3 bubbles but says "1 Person"

  • Click "Donate Group With Individual Images" => share sheet suggestion shows the first person's image (the letter A), not all 3 images, and still says "1 Person"

  • Click "Donate Group with One Image" (...using undocumented setImage:forParameterNamed:...) => share sheet suggestion correctly shows the single group image, but still says "1 Person".


Steps to reproduce:
  1. Create a new SwiftUI app with the below code as ContentView.swift.

  2. Edit Info.plist to include NSUserActivityTypes: ["INSendMessageIntent"]

  3. Add a share extension target; edit the target to add INSendMessageIntent under Supported Intents.

  4. Run the app on a device. (Share sheet suggestions don't seem to work in the simulator.)

  5. Try clicking the buttons to donate intents, and then clicking the share button to activate the share sheet.


ContentView.swift:
Code Block
import SwiftUI
import Intents
import IntentsUI
struct ActivityVC: UIViewControllerRepresentable {
  func makeUIViewController(context: Context) -> some UIViewController {
    return UIActivityViewController(activityItems: [UIImage(systemName: "photo")!], applicationActivities: nil)
  }
  func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
}
struct ContentView: View {
  @State var showActivityVC = false
   
  var body: some View {
    VStack(spacing: 24) {
      Button("Donate Single Without Image") {
        let person1 = INPerson(personHandle: INPersonHandle(value: "Aid", type: .unknown), nameComponents: nil, displayName: "A", image: nil, contactIdentifier: nil, customIdentifier: "Aid")
         
        let intent = INSendMessageIntent(recipients: [person1], outgoingMessageType: .outgoingMessageText, content: nil, speakableGroupName: INSpeakableString(spokenPhrase: "Single"), conversationIdentifier: "1", serviceName: nil, sender: nil, attachments: nil)
         
        INInteraction(intent: intent, response: nil).donate { (err) in
          print("Donated single without image: \(err as Any)")
        }
      }
      Button("Donate Group Without Images") {
        let person1 = INPerson(personHandle: INPersonHandle(value: "Aid", type: .unknown), nameComponents: nil, displayName: "A", image: nil, contactIdentifier: nil, customIdentifier: "Aid")
        let person2 = INPerson(personHandle: INPersonHandle(value: "Bid", type: .unknown), nameComponents: nil, displayName: "B", image: nil, contactIdentifier: nil, customIdentifier: "Bid")
        let person3 = INPerson(personHandle: INPersonHandle(value: "Cid", type: .unknown), nameComponents: nil, displayName: "B", image: nil, contactIdentifier: nil, customIdentifier: "Cid")
         
        let intent = INSendMessageIntent(recipients: [person1, person2, person3], outgoingMessageType: .outgoingMessageText, content: nil, speakableGroupName: INSpeakableString(spokenPhrase: "NoImages"), conversationIdentifier: "2", serviceName: nil, sender: nil, attachments: nil)
         
        INInteraction(intent: intent, response: nil).donate { (err) in
          print("Donated group without images: \(err as Any)")
        }
      }
      Button("Donate Group With Individual Images") {
        let person1 = INPerson(personHandle: INPersonHandle(value: "Aid", type: .unknown), nameComponents: nil, displayName: "A", image: INImage(uiImage: UIImage(systemName: "a.circle.fill")!), contactIdentifier: nil, customIdentifier: "Aid")
        let person2 = INPerson(personHandle: INPersonHandle(value: "Bid", type: .unknown), nameComponents: nil, displayName: "B", image: INImage(uiImage: UIImage(systemName: "b.circle.fill")!), contactIdentifier: nil, customIdentifier: "Bid")
        let person3 = INPerson(personHandle: INPersonHandle(value: "Cid", type: .unknown), nameComponents: nil, displayName: "C", image: INImage(uiImage: UIImage(systemName: "c.circle.fill")!), contactIdentifier: nil, customIdentifier: "Cid")
         
        let intent = INSendMessageIntent(recipients: [person1, person2, person3], outgoingMessageType: .outgoingMessageText, content: nil, speakableGroupName: INSpeakableString(spokenPhrase: "SeparateImages"), conversationIdentifier: "3", serviceName: nil, sender: nil, attachments: nil)
         
        INInteraction(intent: intent, response: nil).donate { (err) in
          print("Donated group with individual images: \(err as Any)")
        }
      }
      Button("Donate Group with One Image") {
        let person1 = INPerson(personHandle: INPersonHandle(value: "Aid", type: .unknown), nameComponents: nil, displayName: "A", image: nil, contactIdentifier: nil, customIdentifier: "Aid")
        let person2 = INPerson(personHandle: INPersonHandle(value: "Bid", type: .unknown), nameComponents: nil, displayName: "B", image: nil, contactIdentifier: nil, customIdentifier: "Bid")
         
        let intent = INSendMessageIntent(recipients: [person1, person2], outgoingMessageType: .outgoingMessageText, content: nil, speakableGroupName: INSpeakableString(spokenPhrase: "OneGroupImage"), conversationIdentifier: "4", serviceName: nil, sender: nil, attachments: nil)
         
        // This "forParameterNamed: \.speakableGroupName" is totally undocumented, but following the example from: https://developer.apple.com/documentation/foundation/app_extension_support/supporting_suggestions_in_your_app_s_share_extension
        intent.setImage(INImage(uiImage: UIImage(systemName: "g.circle.fill")!), forParameterNamed: \.speakableGroupName)
         
        INInteraction(intent: intent, response: nil).donate { (err) in
          print("Donated group with one image: \(err as Any)")
        }
      }
      Button("Delete All") {
        INInteraction.deleteAll { (err) in
          print("Deleted: \(err as Any)")
        }
      }
       
      Spacer().frame(height: 24)
       
      Button(action: { showActivityVC = true }) {
        Image(systemName: "square.and.arrow.up")
      }
    }
    .sheet(isPresented: $showActivityVC) {
      ActivityVC()
    }
  }
}
struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}

Post not yet marked as solved Up vote post of mWKS3JTiu5 Down vote post of mWKS3JTiu5
2.8k views

Replies

I also noticed that if you set speakableGroupName: nil in the "Donate Group With Individual Images" section, it actually says 0 People despite also listing >2 people's names. Screenshot: i.stack.imgur.com/uGDyh.png

Somehow, this works properly for iMessage...

I should also note that I see some log messages that look like this, but they seem harmless:
Code Block text
2021-01-26 16:15:43.083330-0600 SiriTest[53006:5155728] [Intents] -[INCache cacheableObjectForIdentifier:] Unable to find cacheable object with identifier intents-remote-image-proxy:?proxyIdentifier=C92EBC81-3F68-18E6-DF81-8818E0C80E9F.png&storageServiceIdentifier=com.apple.Intents.INImageServiceConnection in cache.

Also filed FB8982187 to track this issue.
Any updates regarding this? I'm dealing with the same issue.

An update? Hit by same issue.

hi even i copy your code to my contentView class , share sheet can not show any suggestion contact item. What am i missed?

  • @JerryLiu, I also was not able to see a suggestion in the share sheet, it turned out to be an issue with the image associated with the intent donation. Per the docs:

    When iOS includes a conversation within your app as a suggestion in the share sheet, it displays your app’s icon along with the INImage you associated with your INSendMessageIntent. If there’s no INImage set on the intent, iOS uses the image property from the INPerson object for each recipient. If the INPerson object’s image is nil, iOS looks up the corresponding contact in the Contacts app using the person’s contactIdentifier. The share sheet then uses the contact’s image.

    I found that if there is no valid image, then the share suggestion is not displayed in the list

Add a Comment