Defer 구문에 대해서 알아보자

유건희·2022년 7월 9일
0

defer

  • Swift에서 defer문을 사용하면 범위가 종료되기 바로 전에 코드를 실행 할 수 있다.

Swift Defer Keyword

  • defer는 크게 2가지 주요 카테고리로 분류 할 수 있다.
  1. Defer Completion : defer문을 사용하면 함수가 반환되기 이전 완료블록을 적잘한 값으로 호출 할 수 있다.
  2. Defer Logic : defer문을 사용하면 함수가 돌아오기 전에 핵심 논리가 실행되도록 보장하기 위해 사용될 수 있다. (file excute)

Defer After Return

  • Swift에서 return이후에 defer가 실행된다.
  • defer문은 코드에 여러가지 분기 및 경로가 있다 하더라도, 중요 상태를 업데이트 할 수 있다.
func criticalSectionWork(task: Task, lock: NSLock) -> Int {
    // lock.unlock() will always be called before
    // the return statement
    defer {
        lock.unlock()
    }
    
    // Handle results
    lock.lock()
    let result = task.perform()
    
    if result == .success {
        modifyDatabase(task: task) 
        return 0
    }
    else if result == .error { 
        return -1 
    }
    else { 
        return -2 
    }
}

Defer Completion

  • 여러 상황에서 상태를 관리하는 것은 쉽게 에러를 만들 수 있는 코드가 된다.
  • defer문을 사용하여 항상 완료 블록을 호출할 수 있다.
func process(tasks: [Tasks], completion: ([Int]?, Error?) -> Void) {
    var results = [Int]()
    var error: Error?
    
    // completion will be always executed when this 
    // function ends, even if there are multiple branches 
    // of logic later in the function implementation
    defer {
        completion(results, error)
    }
    
    for task in tasks {
        do {
            results.append(task.perform())
        }
        catch let taskError {
            error = taskError
            break
        }
    }
    
    if let error = error {
        results = nil
    }
}

Defer Logic

  • defer를 사용하여 함수의 완료 부분에서 파일 닫기와 같은 코드 블록을 실행할 수 있다.
func write(data: Data, offset: Int) throws {
    // Compute the filepath to write to
    let documentsPath = NSSearchPathForDirectoriesInDomains(
        .documentDirectory,
        .userDomainMask,
        true
    )[0]
    
    let filename = "data.txt"
    let filepath = "\(documentsPath)/\(filename)"
    
    // Open a file handle
    guard let file = FileHandle(forUpdatingAtPath: filepath) else {
        throw WriteError.notFound
    }
    
    // Ensure the file is closed at the end of this function
    defer {
        try? file.close()
    }
    
    // Seek to specified offset
    try file.seek(toOffset: UInt64(offset))
    
    // Write data at specified offset
    file.write(data)
}

Defer Return Value

  • defer를 잘 못 사용하는 경우
func status() -> String {
    var status = "initial"

    // Modifying a value type in the defer statement
    // will not modify the return value
    defer {
        // This assignment does not work
        status = "active"
    }

    return status
}

// Calling the status function will 
// return "initial"
status()

Defer문을 사용이 부적절한 경우

  • 복잡한 함수의 경우 defer를 사용했을 때, 디버깅이 어려워질 수 있습니다.
  • defer에서 반환값이 수정되는 경우 논리적으로 생각해야되는 경우가 많다.

참조문서 : https://www.advancedswift.com/when-to-use-defer-in-swift/#swift-defer-keyword

profile
하고싶은 일이 생기면 될 때 까지 해보자 !!

0개의 댓글