Swift/Tips & Tricks

Swift Tips & Tricks - defer

iosswift 2021. 9. 14. 13:36

Swift 에 defer 라는 keyword 가 있다.

사전적 의미는 연기하다, 

Xcode 내 의미는 

Excutes a set of statements before execution leaves the current block of code. 

 

즉, defer 가 속해있는 block 이 나가기 전에

(block 이 끝 라인까지 읽혀서 끝나거나, 중간에 guard let 등으로 코드를 벗어나게 될 때) 실행된다. 

 

아래는 youtube 에서 가져온 예제 소스이다.

func useFile() {
    let file = try! FileHandle(forReadingFrom: URL(string: "~/temp.txt")!)
    
    
    guard let data = try? file.readToEnd() else { return }
    
    // use this data
    
    // write to the file
    
    file.closeFile()
}

(적절한 try catch 처리는 하지 않았다. 현재 콘텐츠의 요점이 아니기때문에) 

 

useFile 함수에서 어떤 file 을 가져온 후, 끝까지 읽고 data를 이용 , 그 후 file 을 닫는 로직이다. 

 

file 을 열고 조작한 후에는 반드시 파일을 닫고 (closeFile()) 끝내야 하는데, 이 과정중에 에러가 생겨 early exit 될 수도 있다.

(guard let 에서 걸리거나 등등)

이런 경우 file.closeFile() 이 실행되지 못한 채 함수블록이 종료되기 때문에 문제가 생긴다.

 

이를 방지하기 위해서 

func useFile() {
    let file = try! FileHandle(forReadingFrom: URL(string: "~/temp.txt")!)
   
    
    guard let data = try? file.readToEnd() else {
        file.closeFile()
        return 
    }
    
    // use this data
    
    // write to the file
    
    
    file.closeFile()
}

다음과 같이 처리할 수도 있겠지만, 위 예제는 단순한 경우라서 guard let 구문이 하나이고, 이 외에도 많은 early exit 의 경우가 생길 수 있다. 

 

모든 early exit 마다 closeFile 을 선언한다면 코드의 질이 떨어지고, 다른 문제가 생길수도 있다.

 

따라서 이때 defer 를 사용하면 이를 방지할 수 있다. 

 

func useFile() {
    let file = try! FileHandle(forReadingFrom: URL(string: "~/temp.txt")!)
    defer{ file.closeFile()}
    
    guard let data = try? file.readToEnd() else { return }
    
    // use this data
    
    // write to the file
}

해당 코드에서 file 이 정상적으로 열린경우 defer 내 구문이 바로 실행되지 않고 블록이 종료되기 전에 한번 실행되어 

파일이 열린 채 끝나지 않는 다는 것을 보장할 수 있고, 

코드의 질 또한 좋아질 수 있다. 

 

 

출처 : https://www.youtube.com/watch?v=_VswqQqVlHo