오늘은 코드를 보다 첨 보는 구문이 있어서 정리해봤다.
defer
는 클로저 안에서 현재 스코프의 맨 끝에 실행되어야 하는 코드 일부를 넣어서 사용한다.
현재 코드 블록을 나가기 전에 꼭 실행해야 되는 코드를 작성하여 코드가 블록을 어떻게 빠져 나가든 꼭 마무리해야 되는 작업을 할 수 있도록 한다.
func deferTest() {
defer {
print("this is defer")
}
print("one two three")
}
deferTest()
이런 코드를 작성하면
one two three
this is defer
라는 결과를 받을 수 있다.
그렇다면 defer
가 여러개라면 어떻게 될까?
func deferTest() {
defer {
print("defer 1")
}
defer {
print("defer 2")
}
defer {
print("defer 3")
}
print("one two three")
}
deferTest()
defer
3개를 사용해서 코드를 써봤다.
one two three
defer 3
defer 2
defer 1
defer
들이 작성된 순서의 역순으로 호출되는 것을 볼 수 있다.
func deferTest() {
defer {
print("deferTest first defer")
}
for i in 0..<2 {
defer {
print("for defer")
}
print("This is a for \(i)")
}
defer {
print("deferTest last defer")
}
}
deferTest()
위와 같이 중첩된 코드에서 defer
는 어떻게 실행될까?
우선 defer
의 특징을 생각해보자.
defer
가 여러 개일때 작성된 순서의 역순으로 실행된다.defer
가 선언된 코드 블록을 빠져나가기 직전에 실행된다.This is a for 0
for defer
This is a for 1
for defer
deferTest last defer
deferTest first defer
위와 같은 결과를 출력한다.
for
문은 루프가 끝날 때마다 defer
가 호출된다.
그렇다면 throw
와 defer
를 같이 쓰면 어떻게 될까?
func throwDeferTest(isError: Bool) throws -> Void {
defer {
print("This is defer")
}
if isError {
enum DeferError: Error {
case error
}
throw DeferError.error
}
defer {
print("This is last defer")
}
print("end func")
}
print("==error: true==")
try? throwDeferTest(isError: true)
print("==error: false==")
try? throwDeferTest(isError: false)
isError
가 true
라면 에러를 던지게 된다.
==error: true==
This is defer
==error: false==
end func
This is last defer
This is defer
중간에 throw
가 발생해서 함수가 종료될 경우 throw
코드 아래에 선언된 defer
에 도달하지 못한다.
따라서 함수가 종료 되어도 throw
코드 아래에 선언한 defer
는 호출되지 않는다.
guard
와 defer
를 같이 쓰면 어떻게 될까?
func guardDeferTest(_ number: Int?) {
defer {
print("This is Top defer")
}
guard let n = number else {
return
}
defer {
print("This is end defer")
}
print("end func")
}
print("==not optional number==")
guardDeferTest(1)
print("==optional number==")
guardDeferTest(nil)
guard
문으로 number가 nil
일때에는 return 하도록 했다.
==not optional number==
end func
This is end defer
This is Top defer
==optional number==
This is Top defer
throw
와 defer
를 같이 썼을때와 똑같은 결과를 출력한다.