🎉

AppIntentsのエラーは必ずCustomLocalizedStringResourceConvertibleで投げよう

2025/03/19に公開1

Appleが最近押しているApp Intentsですが、メインのfunc perform() async throws -> some IntentResultはエラーを投げられるようになっています。
ユーザーはAutomationやSiriや自分のカスタムショートカットを経由してApp Intentsを起動するのですが、ここで大きな問題があります。

普通にエラーを投げると、下記の画像のようにThe action XXX cloud not run because an unknown error occurred.というエラーに丸められて表示されてしまい、適切なフィードバックになっていません。

仮にユーザーからの問題報告などがあっても、このままではバグ解決もままならないでしょう。

image1

ユーザーに対して事前に定義したエラーメッセージを表示するためにはCustomLocalizedStringResourceConvertibleに適合したエラーを投げる必要があります。対応するWWDCセッションを発見することはできなかったのですが、How to signal errors / failures in iOS App Intents?というStackoverflowの回答でこの方法を発見しました。

例えば、perform内部でエラーをスローする関数を利用している場合のサンプルを書くと以下のような感じです(動作するコードではないので、あくまで参考に留めてください)

イメージコード
struct MyIntent: AppIntent {
    static let title = "Start My Intent"
    
    enum MyIntentError: Swift.Error, CustomLocalizedStringResourceConvertible {
        case fileError(NSError)
        case authorizationError(AuthorizationError)
        
        var localizedStringResource: LocalizedStringResource {
            switch self {
            case .fileError(let nsError):
                return LocalizedStringResource("File Error: \(nsError.localizedDescription)")
                
            case .authorizationError(let error):
                return LocalizedStringResource("Activity Authorization Error: \(error.localizedDescription)")
            }
        }
    }
    
    func perform() async throws -> some IntentResult {
        
       var entities: [Entity] = []
       do {
          entities = try database.query()
       } catch {
           throw MyIntentError.fileError(error)
       }
       
       do {
           let activity = try Activity.request(...)
       } catch let error as AuthorizationError {
           throw MyIntentError. authorizationError(error)
       } 
       
        return .result()
    }
    
}

このようにCustomLocalizedStringResourceConvertibleに適合したエラーを投げると下記画像のように、意図したエラーの文章を表示してくれるようになります。AppIntentsでは必須のテクニックだと思いますので、ぜひご活用ください。

image2

GitHubで編集を提案

Discussion