Swift의 온도
Swift #15 - 에러처리
IT의 온도
2021. 1. 26. 00:43
1. 예외 상황
- 예외 상황
#예외가 발생할 수 있는 상황
*파일 처리 중 디스크 에러
*권한이 부족한 상황
#에러 발생해도 크래쉬 되지 않도록
- 에러 발생 API
#예외가 발생할 수 있는 상황
*throws로 선언
*파일에 저장 API
func write(toFile: String,
atomically useAuxiliaryFile:Bool,
encoding enc: String.Encoding) throws
|
cs |
- throws 함수 호출하기
#throws 함수 호출하기
*try를 이용해서 호출
*컴파일 에러 안 남
*그러나 에러 발생 - 애플리케이션 크래쉬
try str.write(toFile: filePath, atomically: true, encoding: .utf8)
|
cs |
- 에러 다루기
#에러 다루기
*에러가 발생 -> 애플리케이션의 크래쉬 방지
*do-catch 블로과 함께 사용
*에러가 발생하면 catch 내 코드 실행
do {
try str.write(toFile: wrongFilePath,
atomically: true, encoding: .utf8)
}
catch {
print("에러 발생")
}
|
cs |
#발생한 에러 정보 얻기
*catch에서 에러 바인딩
do {
try str.write(toFile: wrongFilePath, atomically: true,
encondig: .utf8)
}
catch let error {
print("에러 발생", error)
}
|
cs |
- 반환값과 에러
#반환값이 있는 함수의 에러
init(contentsOffile path: String)) throws{}
func increasePositive(num : Int) throws -> int {}
*try를 이용한 호출
let str = try String(contentsOfFile: filePath)
let num = try incresePositive(num: 99)
*에러 다루기 : do-catch
do {
let str3 = try String(contentsOfFile: wrongFilePath)
}
catch let error {}
|
cs |
#try? 로 호출하기
*에러 발생 시 nil 반환
*반환 타입은 옵셔널
let str = try? String(contentsOfFile: wrongFilePath)
|
cs |
#try! 로 호출하기
*에러 발생 시 애플리케이션 크래쉬
*반환 타입은 언래핑(non-optional)
let str = try? String(contentsOfFile: wrongFilePath)
|
cs |
2. 커스텀 에러 정의
- 에러 정의
#커스텀 에러 정의
*Error 프로토콜
*NSError 클래스(Foundation 프레임워크)
#Error 프로토콜로 커스텀 에러 정의
*Enum으로 정의
*Struct/Class로 정의
#Enum으로 에러 정의
*Enum의 원소 타입을 Error으로
enum CustomError : Error {
case myFault
case yourFault
}
*에러 발생시키기 : throw
throw CustomError.myFault
|
cs |
#구조체와 클래스로 에러 작성
*Error 프로토콜 채택
struct CustomErrorStruct : Error {
var msg : String
}
class CustomErrorClass : Error {
}
*에러 발생 시키기
let error = CustomErrorStruct(msg:"Oooops!")
throw error
|
cs |
- 에러 다루기
#에러 구분하기
*Enum으로 정의한 개별 에러 다루기
*catch 에서 Enum에 에러 나열
*swtich-case와 비슷한 방식
do {
throw CustomError.youtFault
}
catch CustomError.myFault {
print("내탓")
}
catch CustomError.youtFault {
print("남탓")
}
*struct/class로 정의한 에러
*where를 이용한 타입 체크로 구별
do {
let error = CustomErrorStruct(msg:"Oooops!")
throw error
}
catch let error where error is CustomErrorStruct {
print("구조체로 작성한 에러 발생")
}
catch let error where error is CustomErrorClass {
print("클래스로 작성한 에러 발생")
}
catch let error {
print("그외 에러 발생", error)
}
|
cs |
3. 에러 발생 가능 API 작성
- 에러가 발생할 수 있는 함수
#에러 발생 가능한 함수 작성
*0 보다 큰 수만 입력
*그 외 입력값에는 에러
func inputPositive(val : int) throws {
guard val > 0 else {
throw CustomError.yourFault
}
print("정상 수행")
}
*호출/에러 다루기
do {
try inputPositive(0)
} catch {
print("에러 발생")
}
|
cs |
- 반환값이 잇는 함수와 에러
#반환값이 있는 에러 발생 가능 함수
*0보다 큰 수를 입력 가능, 1증가된 값 반환
*그 외 입력에는 에러 발생
func inputPositive(num : int) throws -> Int {
guard num > 0 else {
throw CustomError.yourFault
}
return num + 1
}
|
cs |
#반환값이 있는 에러 발생 함수 사용하기
*호출, 에러 처리, 반환값 얻기
do {
let ret = try increasePositive(num: 1)
}
catch let error {
}
*try? 로 호출/에러 발생 - nil 반환
let reslut = try? dangerousFunction()
*try!로 호출/에러 발생 시 = 크래쉬
let result = try! dangerousFunction()
|
cs |
- 내부에서 에러 다루기
#함수 내부에서 에러 다루기
*함수 내부에 에러 발생 가능 함수 호출
*do-catch로 함수 내부에서 에러 다루기
func dolt() {
do {
try dangerousFunction()
}
catch let error {
print("에러를 함수 내부에서 다루기", error)
}
}
*호출
dolt()
|
cs |
- 발생한 에러를 전파하는 함수
#내부에서 발생한 에러 전파
*함수 내부에 do-catch 없음. throws 작성
func dolt2() throws {
//에러를 처리하지 않고 전파한다.
try dangerousFunction()
}
*호출. throws 함수이므로 try, do-catch 사용
do {
try dolt2()
}
catch let error {
}
|
cs |
- 에러 발생 클로저
#에러 발생 클로저를 사용하는 함수 정의
*파라미터에서
func dolt(_ arg : () throws -> () ) {
}
*반환 타입에서
func dolt2() -> throws -> () {
return dangerousFunction
}
|
cs |
#클로저에서만 발생한 에러 전파 : rethrow
func dolt3(_ arg : () throws -> () ) rethrow {
try arg()
}
*함수 사용하기, 클로저 파라미터로 입력
do {
try dolt3 {
throw CustomError.myFault
}
}
catch let error {
}
|
cs |
4. 클린업
- 에러가 발생할 수 있는 함수
#클린업(defer)
*try-catch-finally 와 유사 그러나 다름
*finally는 try-catch와 함께 작성
*defer는 예외가 발생하는 곳에 작성
func dangerousFunction() throw {
defer {
print("동작 마무리")
}
throw CustomErrorStruct(msg: "에러 발생!")
}
|
cs |