Edited at

タイムアウト時のError(NSError)判定を短く書くのはどうでしょうか


結論

例えば次のようなExtensionどうよ、というのを思いついた。

extension Error {

var isTimeOut: Bool {
let nsError = self as NSError
return (nsError.domain == NSURLErrorDomain && nsError.code == NSURLErrorTimedOut) ? true : false
}
}


導入

FoundationのNSErrorでタイムアウトかどうかを判定する時、ErrorをNSErrorにキャストしてたりすると処理が冗長になったりする。

例えばこんな感じ

let nsError as error

if nsError.domain == NSURLErrorDomain && nsError.code == NSURLErrorTimedOut {
// タイムアウト
}

このような2つの定数と比較するの短くしたいよねっていう思いつきの話です。

んで、APIKitを使っていると、SessionTaskErrorのenumからErrorを取り出さないといけなかったりする。

// APIKitのSessionTaskError

public enum SessionTaskError: Error {
/// Error of `URLSession`.
case connectionError(Error)

/// Error while creating `URLReqeust` from `Request`.
case requestError(Error)

/// Error while creating `Request.Response` from `(Data, URLResponse)`.
case responseError(Error)
}

ViewControllerでエラーに従ってハンドリングしたくなった場合はViewControllerでまずerrorを取り出して...とかやってるとコード読むの大変だなと。

if let error = error {

if case .connectionError(let urlSessionError) = error, nsError.domain == NSURLErrorDomain && nsError.code == NSURLErrorTimedOut)
urlSessionError.isTimeOut {

なので、最初の結論に上げたようにExtensionでやったらどうなのよってのを思いついたわけです。

もちろん最初のコードは一行で書けるのでそこは好みや決めでいいとは思います。

extension Error {

var isTimeOut: Bool {
return (self as NSError).domain == NSURLErrorDomain && (self as NSError).code == NSURLErrorTimedOut
}
}

最初、何で三項演算子使ってたかというと、条件判定の.domainと.codeが条件通りかどうかというのと、このメソッドがtrueかfalse返すのは結果がたまたま同じだから、その結果は別という考えがあるからです。理解されないかもしれないけど、条件は条件、結果は結果として表現したい。だからそのまま結果を返さなかったというわけです。

みなさんはどんな感じでしょうか?


追記

こうすれば簡単に比較できるんでextensionなんて作らないほうが良さそうですね...

if let error = self as? URLError, error.code == URLError.timedOut {

return true
}