defer의 호출순서

func f() {
    defer { print("First defer") }
    defer { print("Second defer") }
    print("End of function")
}
f()
// Prints "End of function"
// Prints "Second defer"
// Prints "First defer"

중첩 블럭에서 호출 순서

func test() {
    defer {
        print("test 1")//8
    }

    do {
        defer {
            print("test 2")//2
        }

        print("test 3")//1
    }

    for i in 0..<2 {
        defer {
            print("test 4")//5
        }

        if i % 2 == 0 {
            defer {
                print("test 5")//4
            }

            print("test 6")//3
        }
    }

    defer {
        print("test 7")//7
    }

    print("test 8")//6
}

// test 3
// test 2
// test 6
// test 5
// test 4
// test 8
// test 7
// test 1

for 문에서 실행문이 한번 돈 다음에 호출됨

2번 돌면 2번 호출됨

defer가 호출되지 않는 경우

1. throw를 이용해서 오류를 던질 경우

defer도 하나의 실행 코드 이기 때문에 defer 구문에 도달하기 전에 함수가 종료되어 버리면 defer가 호출되지 않음. 스택에 저장 될 수 없기 때문에

func test(isError: Bool) throws -> Void{
    defer {
        print("test 1")
    }

    if isError {
        enum TestError: Error {
            case error
        }

        throw TestError.error
    }

    defer {
        print("test 2")
    }

    print("test 3")
}
 
try? test(isError: true) 
//test 1 
try? test(isError: false)
//test 3
//test 2
//test 1

2. guard 문을 사용하여 중간에 함수를 종료하는 경우

마찬가지

func test(string: String?){
    defer {
        print("test 1")
    }

    guard let str = string else {
        return
    }

    defer {
        print("test 2")
    }

    print("test 3")
}
 
test(string: nil) 
// test 1
test(string: "test")
// test 3
// test 2
// test 1

3. 리턴값이 Never(비반환함수)인 경우

에러나면서 함수를 반환하지 않고 종료하기 때문에 defer가 실행되지 않음

비반환함수:

바로 앱 실행을 계속 유지할 수 없는 오류가 발생할 경우 이를 사용자에게 안내하고, 서버에 오류를 보고하는 등의 일을 한 후 프로세스를 종료시킬 때 사용됨