SwiftとnilError
先日、AVAudioFile.read(into:frameCount:)の吐く例外がnilError
という不可解なものになることがあることを知った.
最初は何故nil
なのかと首を傾げたが、どうもnilError
というエラーらしい. 不可解だったので調べてみることにした.
Foundation._GenericObjCError.nilError
このnilError
は正式にはFoundation._GenericObjCError.nilError
というものであり, Foundation
のprivateな型なようだった.
このエラーはObjective-CのAPIをSwiftから呼び出した場合に発生する可能性があり, 以下のコードで再現できる.
Objective-CでNSError**
を引数に取る場合に, Swiftではthrows
へと自動的に変換される.
しかしながら, 返り値がゼロ値 (nil
やNO
) であっても実装次第では (上記コードのように) エラーの代入を行わないということが可能であり, その際にnil
にならないように自動的に代入されるエラーがFoundation._GenericObjCError.nilError
のようだ.
公開されていない型である以上, Swift上で確実に判別する方法は恐らく存在せず, typeなどを文字列にすることで判別するなどの方法が考えられる.
参考までに以下のような値をそれぞれ返す.
String(describing: type(of: error)) : _GenericObjCError
"\(error)" : nilError
type(of: error) : _GenericObjCError
error.localizedDescription : The operation couldn’t be completed. (Foundation._GenericObjCError error 0.)
返り値がゼロ値でありながらエラーを代入しないのは適切か
nilError
の正体は前述の通りだが、ここで気になるのはゼロ値を返しつつエラーを代入しないのは適切なのか、という点である.
例えば, 前述のAVAudioFile.read(into:frameCount:)であれば1フレームも読み込めなかった場合はどう扱うかという話になる.
Swiftだと返り値でbool
を返しつつ, 例外を投げれば良さそうだろう. なんだったら読み込んだフレーム数をint
で返しても良い.
そう考えると, Objective-CからSwiftに変換することでこの情報が欠落していることが問題なように感じてくる.
とはいえ, 言っても詮ないことなのでObjective-Cで実装する際は, 大人しくゼロ値を返すときはエラーを代入するようにした方が良さそうです.
参考
記事が気に入ったらチップを送ることができます!
You can give me a cup of coffee :)
Kyash ID: soranoba
Amazon: Wish List
GitHub Sponsor: github.com/sponsors/soranoba
PayPal.Me: paypal.me/soranoba
(Updated: )