我需要集成 Siri 才能使用我的应用程序拨打电话。Siri 在设置的应用支持上识别我的应用。但是当我试图打电话给一些联系人说“在 MyApp 上调用 ContactName”时,它只会显示“打开 MyApp”按钮。IntentHandler.swift 包含这个函数:
class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling, INStartAudioCallIntentHandling {
override func handler(for intent: INIntent) -> Any {
// This is the default implementation. If you want different objects to handle different intents,
// you can override this and return the handler you want for that particular intent.
return self
}
func handle(startAudioCall intent: INStartAudioCallIntent, completion: @escaping (INStartAudioCallIntentResponse) -> Swift.Void) {
let response: INStartAudioCallIntentResponse
defer {
completion(response)
}
let contacts = (intent.contacts ?? []).filter({ (contact) -> Bool in
return contact.personHandle?.type == .phoneNumber && contact.personHandle?.value != nil
})
// Ensure there is a contact and a handle
guard contacts.count > 0 else {
response = INStartAudioCallIntentResponse(code: .failure, userActivity: nil)
return
}
let userActivity = NSUserActivity(activityType: "INStartAudioCallIntent")
response = INStartAudioCallIntentResponse(code: .continueInApp, userActivity: userActivity)
completion(response)
}
func resolveContacts(forStartAudioCall intent: INStartAudioCallIntent, with completion: @escaping ([INPersonResolutionResult]) -> Void) {
var resolutionResults = [INPersonResolutionResult]()
if let recipients = intent.contacts {
if recipients.count == 0 {
let response = [INPersonResolutionResult.needsValue()]
completion(response)
return
} else if recipients.count == 1 {
if let recipient = recipients.first {
if self.containContact(displayName: (recipient.displayName)) {
resolutionResults.append(INPersonResolutionResult.success(with: recipient))
} else {
resolutionResults.append(INPersonResolutionResult.unsupported())
}
}
} else if recipients.count > 1 {
resolutionResults.append(INPersonResolutionResult.disambiguation(with: recipients))
} else {
resolutionResults.append(INPersonResolutionResult.unsupported())
}
}
completion(resolutionResults)
}
func confirm(startAudioCall intent: INStartAudioCallIntent, completion: @escaping (INStartAudioCallIntentResponse) -> Swift.Void) {
let userActivity = NSUserActivity(activityType: "INStartAudioCallIntent")
let response = INStartAudioCallIntentResponse(code: .ready, userActivity: userActivity)
completion(response)
}
// MARK: - INSendMessageIntentHandling
// Implement resolution methods to provide additional information about your intent (optional).
func resolveRecipients(forSendMessage intent: INSendMessageIntent, with completion: @escaping ([INPersonResolutionResult]) -> Void) {
if let recipients = intent.recipients {
// If no recipients were provided we'll need to prompt for a value.
if recipients.count == 0 {
completion([INPersonResolutionResult.needsValue()])
return
}
var resolutionResults = [INPersonResolutionResult]()
for recipient in recipients {
let matchingContacts = [recipient] // Implement your contact matching logic here to create an array of matching contacts
switch matchingContacts.count {
case 2 ... Int.max:
// We need Siri's help to ask user to pick one from the matches.
resolutionResults += [INPersonResolutionResult.disambiguation(with: matchingContacts)]
case 1:
// We have exactly one matching contact
resolutionResults += [INPersonResolutionResult.success(with: recipient)]
case 0:
// We have no contacts matching the description provided
resolutionResults += [INPersonResolutionResult.unsupported()]
default:
break
}
}
completion(resolutionResults)
}
}
func resolveContent(forSendMessage intent: INSendMessageIntent, with completion: @escaping (INStringResolutionResult) -> Void) {
if let text = intent.content, !text.isEmpty {
completion(INStringResolutionResult.success(with: text))
} else {
completion(INStringResolutionResult.needsValue())
}
}
// Once resolution is completed, perform validation on the intent and provide confirmation (optional).
func confirm(sendMessage intent: INSendMessageIntent, completion: @escaping (INSendMessageIntentResponse) -> Void) {
// Verify user is authenticated and your app is ready to send a message.
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSendMessageIntent.self))
let response = INSendMessageIntentResponse(code: .ready, userActivity: userActivity)
completion(response)
}
// Handle the completed intent (required).
func handle(sendMessage intent: INSendMessageIntent, completion: @escaping (INSendMessageIntentResponse) -> Void) {
// Implement your application logic to send a message here.
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSendMessageIntent.self))
let response = INSendMessageIntentResponse(code: .success, userActivity: userActivity)
completion(response)
}
// Implement handlers for each intent you wish to handle. As an example for messages, you may wish to also handle searchForMessages and setMessageAttributes.
// MARK: - INSearchForMessagesIntentHandling
func handle(searchForMessages intent: INSearchForMessagesIntent, completion: @escaping (INSearchForMessagesIntentResponse) -> Void) {
// Implement your application logic to find a message that matches the information in the intent.
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSearchForMessagesIntent.self))
let response = INSearchForMessagesIntentResponse(code: .success, userActivity: userActivity)
// Initialize with found message's attributes
response.messages = [INMessage(
identifier: "identifier",
content: "I am so excited about SiriKit!",
dateSent: Date(),
sender: INPerson(personHandle: INPersonHandle(value: "sarah@example.com", type: .emailAddress), nameComponents: nil, displayName: "Sarah", image: nil, contactIdentifier: nil, customIdentifier: nil),
recipients: [INPerson(personHandle: INPersonHandle(value: "+1-415-555-5555", type: .phoneNumber), nameComponents: nil, displayName: "John", image: nil, contactIdentifier: nil, customIdentifier: nil)]
)]
completion(response)
}
// MARK: - INSetMessageAttributeIntentHandling
func handle(setMessageAttribute intent: INSetMessageAttributeIntent, completion: @escaping (INSetMessageAttributeIntentResponse) -> Void) {
// Implement your application logic to set the message attribute here.
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSetMessageAttributeIntent.self))
let response = INSetMessageAttributeIntentResponse(code: .success, userActivity: userActivity)
completion(response)
}
func containContact(displayName: String) -> Bool {
//fetch contacts and check, if exist retun YES else NO
return true
}
}
}
let contacts = (intent.contacts ?? []).filter({ (contact) -> Bool in
return contact.personHandle?.type == .phoneNumber && contact.personHandle?.value != nil
})
// Ensure there is a contact and a handle
guard contacts.count > 0 else {
response = INStartAudioCallIntentResponse(code: .failure, userActivity: nil)
return
}
let userActivity = NSUserActivity(activityType: "INStartAudioCallIntent")
response = INStartAudioCallIntentResponse(code: .continueInApp, userActivity: userActivity)
}
我做错了什么?我错过了什么?