エラー処理
エラー処理構文
エラーの理解
1)コンパイル時のエラー=>>sweet構文に関連するエラー(コンパイラから事前に知っておく必要があるというメッセージが表示されます)
2)運転中にエラーが発生しました=>
==>>発生する可能性のあるエラーを事前に処理すると、強制終了(開発者が処理しなければならないエラー)
(実行時)エラー処理が必要なのはなぜですか?
- 앱이 실행하는 중간에 왜 꺼질까?
- 어떤 얘기치 못한 상황이 발생할 수 있음
- (네트워크 통신을 하는 등의 경우에서) 서버에서 데이터를 못 받아와서 ==> 꺼짐
- 앱이 그냥 꺼지는 게 좋은가? 아니면 예를들어 "서버에서 문제가 발생했습니다.
잠시뒤에 다시 접속해 주세요"라고 알려주는 것이 좋은 가?
- 프로세스 중에서, 예외적인 상황(에러)이 발생하는 것이 미리 가능성 등을 처리해 놓으면
앱이 무작정 꺼지는 것을 예방할 수 있음 ⭐️
- 에러는 일반적으로 동작. 즉, 함수의 처리과정에서 일어남
- 함수를 정의할때
예외적인 일이 발생하는 경우가 발생할 수 있는 함수라고 정의하고 처리하는 과정을 배울 것임
- (에러 발생 가능)함수 ====> 함수 실행시에 조금 다르게 처리해야함(에러 처리) ⭐️
エラー処理手順(手順3)
1)定義エラー(事前定義で発生するエラー)
enum HeightError: Error { //에러 프로토콜 채택 (약속)
case maxHeight
case minHeight
}
2)エラーが発生する可能性のある関数の定義
func checkingHeight(height: Int) throws -> Bool {
// (에러를 던잘수 있는 함수 타입이다)
if height > 190 {
throw HeightError.maxHeight
} else if height < 130 {
throw HeightError.minHeight
} else {
if height >= 160 {
return true
} else {
return false
}
}
}
3)エラーが発生する可能性のある関数の処理(関数の実行)
===>既存とは少し異なります(try文とdo-catch文で処理)
do {
let isChecked = try checkingHeight(height: 200)
print("놀이기구 타는 것 가능: \(isChecked)")
} catch {
print("놀이기구 타는 것 불가능")
}
エラーの処理方法-try/try?/try!
1)エラー式の処理方法
do {
let isChecked = try checkingHeight(height: 200)
if isChecked {
print("청룡열차 가능")
} else {
print("후룸라이드 가능")
}
} catch {
print("놀이기구 타는 것 불가능")
}
2) try? (オフセット量)===>オフセットタイプに復元(1)通常は=>(通常)戻りタイプで返す
(2)エラーが発生した場合=>nilが返す
let isChecked = try? checkingHeight(height: 200)
3) try! (Forced trie)==>>エラーが発生しない場合にのみ使用可能(1)通常は=>(通常)戻りタイプで返す
(2)エラー発生時==>ランタイムエラー
let isChecked2: Bool = try! checkingHeight(height: 150) // Bool
Catch Block処理方法
catch blockはdo blockで発生したエラーを処理するblockです
すべてのエラーを処理する必要があります(グローバルスキャンですべてのエラーを処理しない場合、コンパイルエラーは発生しません).
パターンが存在する場合(すべてのエラーを別々に処理する必要があります)
do {
let isChecked = try checkingHeight(height: 100)
print("놀이기구 타는 것 가능: \(isChecked)")
} catch HeightError.maxHeight {
// where절을 추가해서, 매칭시킬 에러패턴에 조건을 추가할 수 있음
print("키가 커서 놀이기구 타는 것 불가능")
} catch HeightError.minHeight { // 생략가능
print("키가 작아서 놀이기구 타는 것 불가능")
}
catchモードなしで処理可能do {
let isChecked = try checkingHeight(height: 100)
print("놀이기구 타는 것 가능: \(isChecked)")
} catch { // error 상수를 제공 (모든 에러가 넘어옴)
print(error.localizedDescription)
if let error = error as? HeightError {
// 실제 우리가 정의한 구체적인 에러 타입이 아니고, 에러 타입(프로토콜)이 넘어올 뿐
switch error {
case .maxHeight:
print("키가 커서 놀이기구 타는 것 불가능")
case .minHeight:
print("키가 작아서 놀이기구 타는 것 불가능")
}
}
}
放出エラーの関数の処理
// 에러정의
enum SomeError: Error {
case aError
}
// 에러를 던지는 함수 정의 (무조건 에러를 던진다고 가정)
func throwingFunc() throws {
throw SomeError.aError
}
// 에러의 처리
do {
try throwingFunc()
} catch {
print(error)
}
通常の関数として処理// 함수 내부에서 do-catch문으로 에러를 처리
// 즉, 발생한 에러를 catch블럭에서 받아서 알맞은 처리
func handleError() {
do {
try throwingFunc()
} catch {
print(error)
}
}
handleError()
1-投げ関数で再度投げ間違い
/**====================================================
- 함수 내에서 에러를 직접처리하지 못하는 경우, 에러를 다시 던질 수 있음
====================================================**/
func handleError1() throws {
//do {
try throwingFunc()
//} // catch블럭이 없어도 에러를 밖으로 던질 수 있음 ⭐️
}
do {
try handleError1() // 에러를 받아서 처리 가능
} catch {
print(error)
}
2-ロールバック関数を使用したロールバックエラー(ロールバックキー)
/**================================================================
- 에러를 던지는 throwing함수를 파라미터로 받는 경우, 내부에서 다시 에러를 던지기 가능
- rethrows키워드 필요 (Rethrowing메서드)
==================================================================**/
// 다시 에러를 던지는 함수(방법1)
func someFunction1(callback: () throws -> Void) rethrows {
try callback() // 에러를 다시 던짐(직접 던지지 못함)
// throw (X)
}
// 다시 에러를 던지는 함수(방법2) - 에러변환
func someFunction2(callback: () throws -> Void) rethrows {
enum ChangedError: Error {
case cError
}
do {
try callback()
} catch { // catch구문에서는 throw (O)
throw ChangedError.cError // 에러를 변환해서 다시 던짐
}
}
// 실제 에러를 다시던지는(rethrowing)함수를 처리하는 부분
do {
try someFunction1(callback: throwingFunc)
} catch {
print(error)
}
do {
try someFunction2(callback: throwingFunc)
} catch {
print(error)
}
メソッド/作成者
/**=======================================================================
- 에러는 1)Throwing함수 뿐만아니라, 2) 메서드와 3)생성자에도 적용 가능
- 에러는 던질 수 있는 메서드는 Throwing메서드, 에러는 던질 수 있는 생성자는 Throwing생성자
=========================================================================**/
// 에러 정의
enum NameError: Error {
case noName
}
// 생성자와 메서드에도 적용 가능
class Course {
var name: String
init(name: String) throws {
if name == "" {
throw NameError.noName
} else {
self.name = name
print("수업을 올바르게 생성")
}
}
}
// 에러 처리 (생성자에 대한)
do {
let _ = try Course(name: "스위프트5")
} catch NameError.noName {
print("이름이 없어 수업이 생성 실패하였습니다.")
}
作成者とメソッドの再定義
class NewCourse: Course {
override init(name: String) throws {
try super.init(name: name)
}
}
/**=================================================================
- Throwing 메서드/생성자는 재정의할 때, 반드시 Throwing메서드/생성자로 재정의해야함
(Throwing 메서드/생성자를 일반 메서드/생성자로 재정의 불가)
- 일반 메서드/생성자를 Throwing 메서드/생성자로 재정의 하는 것은 가능
(일반 메서드/생성자의 범위가 더 큼)
[상속관계에서]
- (상위) throws (하위) throws재정의 (O 가능)
- (상위) 일반 (하위) throws재정의 (O 가능)
(상위) throws (하위) 일반재정의 (X 불가능)
- (상위) throws (하위) rethrows재정의 (O 가능)
(상위) rethrows (하위) throws재정의 (X 불가능)
- Throwing메서드와 Rethrowing메서드를 비교하면 Rethrowing메서드의 범위가 더 작음
===================================================================**/
Reference
この問題について(エラー処理), 我々は、より多くの情報をここで見つけました https://velog.io/@wntdwl/에러처리-Error-Handlingテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol