私のアプリケーションでは、EUR と USD 通貨のみをサポートしています。たとえば、ユーザーが Siri で支払いを GBP に送信しようとすると、EUR と USD のどちらかを選択するように求めます。
その後、画面に次のように表示されます。
- 100ドル
- 100ユーロ
100$ を選択すると、intent.currencyAmount!.currencyCode
常に GBP になります (ただし、ユーザーはドルを選択しました)。とても奇妙です。
これが私のコードです:
func resolveCurrencyAmount(forSendPayment intent: INSendPaymentIntent, with completion: @escaping (INCurrencyAmountResolutionResult) -> Void) {
if let currencyAmount = intent.currencyAmount { // need to check if we have proper value
if let amount = currencyAmount.amount {
if amount.doubleValue == 0 { // wrong amount
completion(INCurrencyAmountResolutionResult.unsupported())
return
}
if let currencyCode = currencyAmount.currencyCode {
if let _ = EnumCurrency(rawValue: currencyCode) { // we found currency code that we know
completion(INCurrencyAmountResolutionResult.success(with: INCurrencyAmount(amount: NSDecimalNumber(value: abs(amount.doubleValue)), currencyCode: currencyCode)))
return
}
}
// if we are here so we don't have proper currency, try to offer user to choose the same amount but with all possible currencies
let disambiguationArray: [INCurrencyAmount] = EnumCurrency.allValues.map({ (currency) -> INCurrencyAmount in
return INCurrencyAmount(amount: NSDecimalNumber(value: abs(amount.doubleValue)), currencyCode: currency.rawValue)
})
completion(INCurrencyAmountResolutionResult.disambiguation(with: disambiguationArray))
}
}
else { // we don't have value
completion(INCurrencyAmountResolutionResult.needsValue())
}
}
enum EnumCurrency : String {
case EUR = "EUR"
case USD = "USD"
static let allValues = [EUR, USD]
}
更新:再現方法(デビッドの質問による):
1) 新しいインテント拡張を作成する
2) plist ファイルでは、1 つのタイプのインテントのみを残します: http://take.ms/pt16N
3) IntentHandler クラス (xCode によって作成されます) は、INSendPaymentIntentHandling プロトコルに確認する必要があります
4) IntentHandler クラスにこれを追加します。
func resolveCurrencyAmount(forSendPayment intent: INSendPaymentIntent, with completion: @escaping (INCurrencyAmountResolutionResult) -> Void) {
if let currencyAmount = intent.currencyAmount { // need to check if we have proper value
if let amount = currencyAmount.amount {
if amount.doubleValue == 0 { // wrong amount
completion(INCurrencyAmountResolutionResult.unsupported())
return
}
if let currencyCode = currencyAmount.currencyCode {
if let _ = EnumCurrency(rawValue: currencyCode) { // we found currency code that we know
completion(INCurrencyAmountResolutionResult.success(with: INCurrencyAmount(amount: NSDecimalNumber(value: abs(amount.doubleValue)), currencyCode: currencyCode)))
return
}
}
// if we are here so we don't have proper currency, try to offer user to choose the same amount but with all possible currencies
let disambiguationArray: [INCurrencyAmount] = EnumCurrency.allValues.map({ (currency) -> INCurrencyAmount in
return INCurrencyAmount(amount: NSDecimalNumber(value: abs(amount.doubleValue)), currencyCode: currency.rawValue)
})
completion(INCurrencyAmountResolutionResult.disambiguation(with: disambiguationArray))
}
}
else { // we don't have value
completion(INCurrencyAmountResolutionResult.needsValue())
}
}
enum EnumCurrency : String {
case EUR = "EUR"
case USD = "USD"
static let allValues = [EUR, USD]
}
// MARK: - Confirm
func confirm(sendPayment intent: INSendPaymentIntent, completion: @escaping (INSendPaymentIntentResponse) -> Void) {
// success
completion(INSendPaymentIntentResponse(code: INSendPaymentIntentResponseCode.success, userActivity: nil))
}
// MARK: - Handle
func handle(sendPayment intent: INSendPaymentIntent, completion: @escaping (INSendPaymentIntentResponse) -> Void) {
// just for test
completion(INSendPaymentIntentResponse(code: .failureRequiringAppLaunch, userActivity: userActivity))
}
5) そして、Siri で起動できます。中国の通貨またはその他の非正規通貨を選択すると、コードで EUR と USD のどちらかを選択するように指示されますが、その後、RESOLVE 関数で (siri が必要なときに呼び出されます)より多くの時間で通貨を解決します) 中国の通貨を取得します (すべてのボタン インターフェイスは Siri によって提供されるため、David が尋ねたようなボタンのコードを追加する必要はありません)