LoginSignup
1172
1067

More than 1 year has passed since last update.

Swiftのエラー4分類が素晴らしすぎるのでみんなに知ってほしい

Last updated at Posted at 2017-01-14

 Swift Tweets  Qiita 稿


Q&A

 @koher  "Swift4"  #swtws
 koher (@koher) 2017114

1: Swift 4


 Swift 2.0  Core Team  "Error Handling Rationale and Proposal"  try! Swift 

11 try! Swift 





Simple domain error

Recoverable error

Universal error

Logic failure


4

  


 toInt  "123"  "xyz" 

Simple domain error




Swift  Optional 使 Int?  nil  Simple domain error 
func toInt(_ string: String) -> Int? { ... }

guard let number = toInt(string) else {
  print("整数を入力して下さい。")
  return
}

// `number` を使う処理

Recoverable error


 Int 

Swift  Error  Recoverable error  toInt  throws  do- try - catch 使
func toInt(_ string: String) throws -> String { ... }

do {
  let number = try toInt(string)
  // `number` を使う処理
} catch ConversionError.overflow {
  print("\(Int.min)\(Int.max)の値を入力して下さい。")
  return
} catch {
  print("整数を入力して下さい。")
  return
}

Recoverable  Universal error  Logic failure    Simple domain error  Recoverable error 

Universal error


 toInt 

Swift  Universal error  fatalError 使 Swift 3  fatalError 
func toInt(_ string: String) -> Int {
  guard isPossibleToConvert(string) else {
    fatalError()
  }
  ...
}

let number = toInt(string) // 変換に失敗したらクラッシュ
// `number` を使う処理

Logic failure


 toInt  Logic failure 

Swift  Logic failure  precondition  precondition  -Ounchecked 
func toInt(_ string: String) -> Int {
  precondition(isPossibleToConvert(string))
  ...
}

let number = toInt(string) // 変換に失敗したら未定義動作
// `number` を使う処理

『どのようにエラーに対応させたいか』によってエラーを分類する




 nil  Error  throw 

使




"Error Handling Rationale and Proposal" 4使

Simple domain error 



simple-domain-error.swift
guard let number = Int(string) else {
  print("整数を入力して下さい。")
  return
}

// `number` を使う処理

Recoverable error の例

ファイル入出力やネットワークのエラーが挙げられています。発生条件が明確でなく、どのように回復すべきか原因によって対応方法が異なるので、その手段を提供するべきという考えです。

recoverable-error.swift
// ※説明のために架空の `Data` の `init` を使っています。
do {
  let data = try Data(at: path)
  // `data` を使う処理
} catch FileError.noSuchFile {
  // ファイルがない場合のエラー処理
} catch FileError.permissionDenied {
  // パーミッションがない場合のエラー処理
} catch {
  // その他の場合のエラー処理
}

Universal error の例

メモリ不足やスタックオーバーフローなどのエラーが挙げられています。利用者側で対応しようがないのでプログラムを停止すべきという考えです。

universal-error.swift
func reduce<T, R>(_ range: CountableRange<T>, _ initial: R, _ combine: (R, T) -> R) -> R {
  guard let first = range.first else { return initial }
  return reduce(
    range.startIndex.advanced(by: 1) ..< range.endIndex,
    combine(initial, first),
    combine
  )
}

reduce(0..<1000000, 0) { $0 + $1 } // スタックオーバーフローでクラッシュ

Logic failure の例

Array のインデックスがはみ出てしまった場合や、 nil が入っている Optional に対して Forced unwrapping を実行してしまった場合などが挙げられています。

logic-failure.swift
let array = [2, 3, 5]
print(array[3])

使い分けの考え方


4

 Universal error  Simple domain error 

 Logic failure  Array  Simple domain error nil Dictionary  nil 

 Swift  subscript 

 Array  subscript 

 Array  subscript  Logic failure 

 Array  Universal error 
out-of-bounds.swift
let array = [2, 3, 5]
print(array[3])

 out-of-bounds.swift  -Ounchecked 
run-out-of-bounds.sh
swift -Ounchecked out-of-bounds.swift

Array  Logic failure  -Ounchecked 





 Simple domain error

 Recoverable error

 Universal error

 Logic failure


"Error Handling Rationale and Proposal"

2: Java 


8調

C


使C

C file 使
FILE *file = fopen("filename", "r");
if (file == NULL) { // ファイルを開くのに失敗したとき
  // エラー処理
}
// `file` を使う処理

調

Java  Swift


Java
try { // try-catch を書かないとコンパイルエラー
  RandomAccessFile file = new RandomAccessFile(new File("filename"), "r");
  // `file` を使う処理
} catch (FileNotFoundException e) { // ファイルを開くのに失敗したとき
  // エラー処理
}

 Java  C#  Kotlin 

Java  Java  Swift 

 Swift  Swift 

 Swift  Swift 

defer  finally  rethrows  throws  try  Implicit control flow problem  try! 

UI Simple domain error  Recoverable error  Logic failure  ! try! 

 Java  try!  FormatException  throw  toInt 
int number;
try {
  number = toInt(string);
} catch (FormatException e) {
  throw new RuntimeException("Never reaches here.");
}

Swift なら次の通りです。シンプルですね!

let number = try! toInt(string)

 Logic failure  Java 


 "Error Handling Rationale and Proposal"  Java  Swift 

Java  throw  Throwable  Throwable 


Exception

RuntimeException

Error




Java  Effective Java 


 Exception

 RuntimeException

 Error


使




Recoverable error  Exception

Logic failure  RuntimeException

Universal error  Error


使

 Java  Java  Java 

 try - catch  Java  RuntimeException  ArrayIndexOutOfBoundsException  RuntimeException  Logic failure  Swift 

 RuntimeException  Logic failure 

 RuntimeException  Logic failure  Exception  Recoverable error  catch(Exception e)  Exception  Recoverable error  RuntimeException  Logic failure 

 Logic failure  Effective Java  RuntimeException  catch  RuntimeException  Exception 

 parseInt  RuntimeException catch

 Logic failure  catch  RuntimeException  Logic failure  Logic failure 

 Java  RuntimeException  throw  IllegalArgumentException  RuntimeException 

 Java  Logic failure 

 Logic failure  Array  Logic failure 

 Simple domain error    Simple domain error  Logic failure  Java  Simple domain error  Java 使

Swift 





 Simple domain error Recoverable error  Logic failure  ! try! 

Java  Simple domain error  Logic failure 



2017-01-18



id:sawat IllegalArgumentException  Logic failure 




Logic failure  Array  index out of bounds  Logic failure   IllegalArgumentException 

Simple domain error  removeLast 


: parseInt, JSON 

: pop, Iterator  next 

 

: 


DB

 sqrt(a - b)  a - b  Logic failure  Simple domain error  pop 

 Logic failure  Simple domain error 

 MessageDigest  getInstance 


Simple domain error


  

 Simple domain error  Java  Simple domain error  try-catch  null  null  null  Iterator  next  null  null  Simple domain error  Logic failure 
1172
1067
11

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

1172
1067