Как интегрировать приложение с приложением "Контакты iOS"?

Я пытаюсь интегрировать приложение обмена сообщениями с приложением "Контакты iOS", чтобы пользователи могли инициировать сообщения через приложение непосредственно из "Контактов". Это было рассмотрено на сессии 240 WWDC 2016, но некоторые детали были опущены.

Следуя примеру WWDC, у меня есть:

  • Добавлен тип активности в приложение Info.plist:

    <key>NSUserActivityTypes</key>
    <array>
            <string>INSendMessageIntent</string>
    </array>
    
  • Реализовано application(_:continue:restorationHandler:) в моем делегате приложения.

  • Создал и подарил взаимодействие

    let activity = NSUserActivity(activityType: "com.example.message")  
    activity.title = "Send CB Test Message"  
    activity.expirationDate = Date.distantFuture  
    
    let recipient = INPerson( /* recipient with an email address in my Contacts database */ )  
    let sender = INPerson( /* me */ )        
    
    let intent = INSendMessageIntent(recipients: [recipient], content: nil, groupName: nil, serviceName: "CB Test Chat", sender: sender)  
    
    let response = INSendMessageIntentResponse(code: .success, userActivity: activity)
    let interaction = INInteraction(intent: intent, response: response)  
    interaction.direction = .outgoing  
    interaction.donate { (error) in  
        print("Donated")  
        if let error = error {  
            print("Donate error: \(error)")  
        }  
    }  
    

Такого рода работы. Приложение отображается в качестве опции на одной карточке получателя в Контактах. Нажатие на нее в Контактах запускает мое приложение с NSUserActivity. Это хорошо, но этого недостаточно.

Сессия WWDC использовала WhatsApp в качестве примера. WhatsApp отображается в качестве опции на всех моих контактах, даже на тех, у кого нет аккаунтов в WhatsApp. Я подумал, что, возможно, WhatsApp создал и подарил взаимодействие для всех. Но если я создаю новый контакт, когда WhatsApp не запущен, он сразу становится доступным для этого контакта. Я немного поэкспериментировал, установив для аргумента получателя значение nil или пустой массив, но это не имело никакого эффекта.

Так чего мне здесь не хватает? Я близко, может быть? Но кажется, что пожертвования не могут быть тем, что мне действительно нужно.

Обновление, в ответ на @Mark: разъяснил использование activity. Я пробовал это с помощью response (который использует activity) и с нулевым значением для response но ни один не работал.

Ответы

Ответ 1

Я спросил об этом на WWDC 2019, и мне сказали, что этот вид массового пожертвования работает только для приложений VOIP, а не для приложений обмена сообщениями. Код в этом вопросе теоретически будет работать для VOIP--, может быть, а может и не совсем так, как представлено. Я не пробовал, потому что я не работаю над правильным видом приложений.

Ответ 2

Просто используйте UIActivityViewController. Вы можете создать его с текстом или любым другим объектом. Вы также можете исключить все типы, кроме обмена сообщениями, если это все, что вы хотите.

let objectsToShare = [textToShare, otherObject] as [Any]
            let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)

        //New Excluded Activities Code
        activityVC.excludedActivityTypes = [UIActivityType.addToReadingList]
        //

        activityVC.popoverPresentationController?.sourceView = sender as? UIView
        self.present(activityVC, animated: true, completion: nil)