記事

Intentのハンドル

Intentを実行し、処理内容に関するフィードバックをSiriKitに提供します。

概要

Intentのリゾルブとコンファームが完了すると、SiriKitから、ユーザーのリクエストを実行することでIntentをハンドルするよう求められます。Intentをハンドルする際は、以下を実行します。

  • Intentに対応するタスクを実行する。

  • 何を実行したかに関する情報を格納した、responseオブジェクトを返す。

ほとんどのIntentはIntents App Extensionから直接ハンドルしますが、場合によって、Appにリクエストをハンドルさせるよう、SiriKitに依頼できます。

例:ワークアウト開始Intentをハンドルする

ワークアウトAppではタイマーやその他のヘルスケア関連情報を構成しなければならない場合がありますが、これらのタスクをIntents App Extensionからハンドルするのは容易ではありません。このため、ワークアウトIntentのハンドルでは、SiriKitにAppの起動を指示します。

リスト1は、ワークアウト開始のハンドル方法の例です。このメソッドで作成されるresponseオブジェクトには、SiriKitがAppを起動する必要があることを示すコードが含まれています。

リスト1

ワークアウト開始Intentをハンドルする

func handle(startWorkout intent: INStartWorkoutIntent,
       completion: @escaping (INStartWorkoutIntentResponse) -> Void) {
    // Let the app start the workout. 
    let response = INStartWorkoutIntentResponse(code: .continueInApp,
             userActivity: nil)
    completion(response)
}

例:配車リクエストIntentをハンドルする

配車予約Appは、ユーザーが予約する乗車について詳細な情報を提供する必要があります。配車予約情報を取得するには、自分の組織のサービスとやり取りし、返された情報を使ってINRideStatus(英語)オブジェクトを作成する必要があります。

リスト2は、配車予約リクエストに応答する方法の例を示しています。メソッドの多くは、乗車の詳細情報をINRideStatus(英語)オブジェクトに配置するものです。そのプロセスにおいて、メソッドは乗車の詳細情報を配車予約サービスに伝え、配車される車と運転手の情報を取得します。メソッドは最終的に、INRideStatus(英語)オブジェクトを含むレスポンスをSiriKitに返します。

リスト2

配車リクエストIntentをハンドルする

func handle(requestRide intent: INRequestRideIntent, 
        completion: @escaping (INRequestRideIntentResponse) -> Void) {
    var rideOption : INRideOption? = nil
        
    // Save a reference to the ride for status updates
    self.bookedRideIntent = intent
        
    if let phrase = intent.rideOptionName?.spokenPhrase {
        switch phrase {
        case "SUV":
            rideOption = self.createSUVRideOption(pickup: 
                        intent.pickupLocation!, 
                        dropOff: intent.dropOffLocation!)
            break
        case "Compact":
            rideOption = self.createCompactRideOption(pickup: 
                        intent.pickupLocation!, 
                        dropOff: intent.dropOffLocation!)
            break
        case "Sedan":
            rideOption = self.createSedanRideOption(pickup:
                        intent.pickupLocation!, 
                        dropOff: intent.dropOffLocation!)
            break
                
        default:    // Default to a sedan.
            rideOption = self.createSedanRideOption(pickup:
                        intent.pickupLocation!, 
                        dropOff: intent.dropOffLocation!)
            break
        }
    }
        
    // Create the status for the response.
    let rideStatus = INRideStatus()
    rideStatus.rideOption = rideOption
    let (vehicle, driver) = self.getVehicleAndDriver(intent: intent,
            rideOption: rideOption!)
        
    // Assign the driver and vehicle.
    rideStatus.vehicle = vehicle
    rideStatus.driver = driver
    rideStatus.estimatedPickupDate = 
             self.getPickupTimeForVehicle(vehicle : vehicle)
    rideStatus.pickupLocation = intent.pickupLocation
    rideStatus.dropOffLocation = intent.dropOffLocation

    // Book the ride and get its ID.
    rideStatus.rideIdentifier = 
             self.bookRide(rideDetails : rideStatus)
    
    // Get the current ride phase. 
    rideStatus.phase = 
             self.phaseForRide(identifier : rideStatus.rideIdentifier)

    // Deliver the response to SiriKit
    if rideStatus.phase == .confirmed {
        let response = INRequestRideIntentResponse(code: .success,
               userActivity: nil)
        response.rideStatus = rideStatus
        completion(response)
    } else {
        let activity = NSUserActivity(activityType:
            "com.example.myRideApp.noRideAvailable")
        let response = INRequestRideIntentResponse(code: 
               .failureRequiringAppLaunch, userActivity: activity)
        response.rideStatus = rideStatus
        completion(response)
    }
}

Intentのハンドルに関するヒント

Intentのハンドルでは、以下を考慮します。

  • できるだけ多くの情報をresponseオブジェクトに収容する。Siriやマップは、Intentをコンファーム、ハンドルする際、できるだけ多くの情報をユーザーに伝えようとします。responseオブジェクトに詳細な情報を収容して返せば、Appが何をしたかがユーザーにきちんと伝わり、使い勝手が向上します。

  • データオブジェクトに値をすべて設定してから、responseオブジェクトに代入する。多くの場合、responseオブジェクトのプロパティは、(参照方式でなく)コピー方式で設定するようになっています。データオブジェクトをプロパティとして設定した後、これに対して修正を施しても、元のオブジェクトではなくコピーが修正されるだけです。このため、プロパティ値は必ず、オブジェクトに必要な変更を行ってから設定してください。

  • responseオブジェクトを数秒以内に返す。Siriやマップは頻繁にユーザーとやり取りするので、レスポンスはできるだけ迅速に返さなければなりません。数秒以上かかるのであれば、要求の処理が「進行中」である旨のコードを入れたレスポンスを返してください。

  • Appへのディープリンクに対応するには、カスタムユーザーアクティビティオブジェクトを使用する。デフォルトオブジェクトに代えてカスタムNSUserActivity(英語)オブジェクトを渡すことで、ユーザーインターフェイス設定用の追加情報を提供できます。その情報を利用すると、ユーザーがSiriまたはマップで実行したタスク固有の情報を表示して、ユーザー体験をいっそう向上させることが可能になります。

  • ユーザーアクティビティオブジェクトは常に親Appでハンドルする。Siriまたはマップは、Appに制御を移す必要が生じた場合、発生したイベントの情報を保持しているNSUserActivity(英語)オブジェクトを渡します。ユーザーアクティビティオブジェクトを明示的に提供しない場合は、responseオブジェクトがデフォルトのNSUserActivity(英語)オブジェクトを作成します。これらのオブジェクトをAppでハンドルすることにより、シームレスな体験を確実にユーザーに提供することが可能になります。

SiriKitは、可能ならばユーザーの連絡先データベースから情報を得て、パラメータの値を埋めようとします。しかし、Appがユーザーの連絡先に対するアクセスを拒否された場合、Intentを介して、当該連絡先に関する情報が渡されないかもしれません。例えば、Intent内のいずれかのINPerson(英語)オブジェクトで、spokenPhrase(英語)プロパティにしか値が含まれておらず、その他の連絡先情報がない可能性があります。このような状況ではSiriKitも連絡先の住所にアクセスできず、「<App>で自宅までのタクシーを呼んで」というフレーズからは、降車場所の指定がないIntentが作られることになります。このような場合、アクセスを許可すれば使い勝手がよくなる旨、ユーザーに助言を与えることも考えてみるとよいでしょう。

関連項目

Intentのリゾルブとハンドル

Intentのパラメータをリゾルブする

Intentのパラメータを検証し、続行に必要な情報があることを確認します。

Intentの詳細をコンファームする

Intentパラメータの最終的な検証を行い、サービスがIntentを実行できる状態にあることを確認します。