If you're developing a restaurant reservation application, or an application that makes reservations for you (flights, trains, tickets), you can notify Siri about your reservation details.
In this article, we will create a demo of the booking app. When a user makes a reservation, the app sends the booking information to Siri, which prompts the user to add the booking information to the calendar. When the reservation is viewed, the app will update the reservation time. You can see the system calendar app notify the user about updates to their booking information.
By notifying Siri, users will receive immediate notifications to add events to their calendar.
Siri will also automatically fill in the details of the event venue.
Siri also displays relevant information on the user's screen before booking.
Another benefit is that Siri will automatically update the event details when the app updates the latest information about a particular booking event (based on your booking ID). If there is a change to an existing reservation on the app, the system calendar app will display a notification badge.
import intents
Github: https://github.com/mszmagic/SiriReservationSample
First, write a function that determines how long the reservation will continue. In the demonstration application, I set the restaurant reservation to 2 hours.
private func getReservationPromoteDateRange(_ item: Reservation) -> INDateComponentsRange {
let calendar = Calendar.autoupdatingCurrent
//Promote users to view booking details up to 2 hours after booking time
let promoteDate_end = calendar.date(byAdding: .hour, value: 2, to: item.bookedTime) ?? item.bookedTime
let promoteDate_end_components = calendar.dateComponents(in: TimeZone.autoupdatingCurrent, from: promoteDate_end)
let promoteDate_start = item.bookedTime
let promoteDate_start_components = calendar.dateComponents(in: TimeZone.autoupdatingCurrent, from: promoteDate_start)
//
return .init(start: promoteDate_start_components, end: promoteDate_end_components)
}
You need to create a unique distinguished name for the reserved item.
let reservation_item = INSpeakableString(vocabularyIdentifier: item.reservationID, spokenPhrase: "\(item.restaurantName)Reservation", pronunciationHint: nil)
Then define the action to take when the user wants to see the reservation. You can also provide the URL. This information is used by Siri to know what action to take when a user wants to see a particular booking item:
private func getViewReservationDetailsAction(_ item: Reservation) -> INReservationAction {
let viewDetailsAction = NSUserActivity(activityType: "com.example.SiriReservationSample.viewReservationDetails")
let reservationDateStr = DateFormatter.localizedString(from: item.bookedTime, dateStyle: .short, timeStyle: .short)
viewDetailsAction.title = "\(item.restaurantName)In\(reservationDateStr)View reservation status details at"
viewDetailsAction.userInfo = ["reservationID" : item.reservationID]
viewDetailsAction.requiredUserInfoKeys = ["reservationID"]
viewDetailsAction.webpageURL = generateReservationURL(item)
return .init(type: .checkIn,
validDuration: getReservationPromoteDateRange(item),
userActivity: viewDetailsAction)
}
let reservation = INRestaurantReservation(itemReference: reservation_item,
reservationNumber: item.reservationID,
bookingTime: item.bookedTime,
reservationStatus: item.reservation_status,
reservationHolderName: item.personName,
actions: reservation_actions,
url: generateReservationURL(item),
reservationDuration: getReservationPromoteDateRange(item),
partySize: item.reservation_partySize,
restaurantLocation: item.restruantLocation)
Variable name | Explanation |
---|---|
itemReference | Reference ID objectreservation_item |
reservationNumber | Reservation ID |
bookingTime | Time for the user to make this reservation |
reservationStatus | Reservation status |
reservationHolderName | The name of the person who made this reservation |
actions | Function in this examplegetViewReservationDetailsAction() Output of |
url | URL address (web page) for users to access reservation details |
reservationDuration | Please set the start and end of the reservation.getReservationPromoteDateRange() Function output |
partySize | Number of people eligible for this reservation |
restaurantLocation | Restaurant locationCLPlacemark |
Now you need to enter the reservation into the system.
let intent = INGetReservationDetailsIntent(reservationContainerReference: reservation_item, reservationItemReferences: nil)
let response = INGetReservationDetailsIntentResponse(code: .success, userActivity: nil)
response.reservations = [reservation]
let interaction = INInteraction(intent: intent, response: response)
interaction.donate(completion: completionHandler)
The user will now see a Siri message to add to the calendar event.
The above function must be called each time the user views the reservation (even if the information has not changed). Siri will notify you through the calendar app if your booking details change.
It is important to make sure that your booking ID is the same for one booking.
From the project settings, go to the Info
tab and add information on the supported activity types. The code above uses com.example.SiriReservationSample.viewReservationDetails
as the activity type.
If the user wants to view the reservation, they can launch the application in Siri.
Add the following function in the SceneDelegate.swift
file:
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if userActivity.activityType == "INGetReservationDetailsIntent" {
//
}
}
Here's how to fetch the booking ID:
if let userActivity = notificationObject.object as? NSUserActivity,
let intentObject = userActivity.interaction?.intent as? INGetReservationDetailsIntent,
let reservationName = intentObject.reservationItemReferences?.first,
let reservationID = reservationName.vocabularyIdentifier {
DispatchQueue.main.async {
self.viewingReservationID = .init(reservationID: reservationID)
}
}
I tried to use the userInfo
property, but it doesn't seem to contain the reservation ID. Therefore, please use the above code instead to get the reservation ID.
Previous code settings:
let reservation_item = INSpeakableString(vocabularyIdentifier: item.reservationID, spokenPhrase: "\(item.restaurantName)Reservation", pronunciationHint: nil)
So if you access the variable vocabularyIdentifier
, you will get item.reservationID
.
:relaxed: Twitter @MaShunzhe