enum PhoneError: Error {
case unknown
case batteryLow(batteryLevel: Int)
}
Error 를 표현하기 위해서는 Error 프로토콜을 채택해야 한다.
func checkPhoneBatteryStatus(batteryLevel: Int) throws -> String {
guard batteryLevel != -1 else { throw PhoneError.unknown }
guard batteryLevel > 20 else { throw PhoneError.batteryLow(batteryLevel: batteryLevel) }
return "배터리 상태가 정상입니다."
}
do {
try checkPhoneBatteryStatus(batteryLevel: -1)
} catch PhoneError.unknown {
print("알 수 없는 에러입니다.")
} catch PhoneError.batteryLow(let batteryLevel) {
print("배터리 전원 부족, 남은 배터리 : \(batteryLevel)%")
} catch {
print("그 외 오류 발생 : \(error)")
}
let status1 = try? checkPhoneBatteryStatus(batteryLevel: -1)
print(status1) // nil
let status2 = try? checkPhoneBatteryStatus(batteryLevel: 30)
print(status2) // Optional("배터리 상태가 정상입니다.")
발생한 에러를 try?
로 처리하면 nil
을 반환
에러가 발생하지 않을 것이라고 확신한다면 try!
를 사용하여 강제적으로 Optional
을 해제해줄 수 있다.(권장 X)
전달 인자로 보낼 수 있고, 변수/상수 등으로 저장하거나 전달할 수 있으며, 함수의 반환 값이 될 수도 있다.
{ (매개 변수) -> 리턴 타입 in
실행 구문
}
let hello1 = { () -> () in
print("hello")
}
hello1() // hello
let hello2 = { (name: String) -> String in
return "Hello, \(name)"
}
hello2("Park") // Hello, Park
일반 함수를 호출하듯이 hello2(name: "Park")
처럼 사용하면 에러가 발생한다. 전달인자 레이블을 적지 않아야 한다.
func doSomething1(closure: () -> ()) {
closure()
}
doSomething1(closure: { () -> () in
print("hello")
}) // hello
func doSomething2() -> () -> () {
return { () -> () in
print("hello")
}
}
doSomething2()() // 매개변수를 넣을 수 있는 곳이 2곳이라 이렇게 쓰나 보다.
후행 클로저를 사용하면 클로저를 간단히 표현할 수 있다.
매개변수로 클로저가 여러 개 전달될 경우에는 마지막 매개변수에 해당하는 클로저만 후행 클로저로 사용할 수 있다.
doSomething1() {
print("hello")
}
하나의 클로저만 매개변수로 전달하는 경우에는 매개변수 부분의 소괄호도 생략할 수 있다.
doSomething1 {
print("hello")
}
매개변수로 클로저가 여러 개 전달될 경우
func doSomething3(success: () -> (), fail: () -> ()) {
}
doSomething3 {
실행 코드
} fail: {
실행 코드
}
첫번째 클로저는 전달인자 레이블 생략
func doSomething4(closure: (Int, Int, Int) -> (Int)) {
closure(1, 2, 3)
}
doSomething4(closure: { (a, b, c) in
return a + b + c
}) // 일반적인 호출
doSomething4(closure: {
return $0 + $1 + $2
}) // 파라미터 형식 생략
doSomething4(closure: {
$0 + $1 + $2
}) // 리턴 형식 생략(블록에 리턴 구문만 남는 경우에만 가능)
doSomething4() {
$0 + $1 + $2
} // 후행 클로저 사용
doSomething4 {
$0 + $1 + $2
} // 매개변수로 하나의 클로저만 전달되기 때문에 소괄호까지 생략 가능
다른 함수를 전달 인자로 받거나 함수 실행의 결과를 함수로 반환하는 함수
(map, filter, reduce)
let numbers = [0, 1, 2, 3]
let mapArray = numbers.map { (number) -> Int in
return number * 2
}
print("map \(mapArray)") // map [0, 2, 4, 6]
let intArray = [10, 5, 20, 13, 4]
let filterArray = intArray.filter { $0 > 5 } // 위에서 다룬 클로저 단순화 사용
print("filter \(filterArray)") // filter [10, 20, 13]
let someArray = [1, 2, 3, 4, 5]
let reduceResult = someArray.reduce(0) {
(result: Int, element: Int) -> Int in
print("\(result) + \(element)")
return result + element
} // 0은 초기값, result에는 누적값, element는 배열의 원소
print("reduce \(reduceResult)")
/*
0 + 1
1 + 2
3 + 3
6 + 4
10 + 5
reduce 15
*/