[Swift] Closure - 3 (NoEscaping, Escaping, AutoClosure)

728x90

NoEscaping, Escaping, AutoClosure에 대해 알아 보겠습니다.

Swift 3.0 이전 - @escaping 이 기본
Swift 3.0 이후 - @noescaping 이 기본
@noescaping -> @noescaping 가능
@noescaping -> @escaping 불가능
@escaping -> @noescaping, @escaping 둘 다 가능

 

@noescaping

기본값이 noescaping
해당 함수 범위 내에서만 동작하도록 하고 범위 밖에서는 사용하지 못하도록 한다.

final class someClass {

  var closure: (() -> ()) = {}

  func noEscapingClosure(_ param: () -> ()) {
    // 에러 발생 @escaping을 명시해줘야된다.
    self.closure = param
  }
}

 

@escaping

위의 예제처럼 param을 메서드 밖에서도 사용하고 싶다면 @escaping을 추가해주어야 합니다.
클로저가 함수로부터 escaping한다는 것은 해당 함수의 인자로 클로저가 전달되지만, 함수가 반환된 후 실행 되는 것을 의미합니다. 함수의 인자가 함수의 영역을 탈출하여 함수 밖에서 사용할 수 있는 개념은 기존에 우리가 알고 있던 변수의 scope 개념을 무시합니다. 왜냐하면 함수에서 선언된 로컬 변수가 로컬 변수의 영역을 뛰어넘어 함수 밖 에서도 유효하기 때문입니다.

func escapingClosure(_ param: @escaping () -> ()) {
    self.closure = param
}

보통 completion handler에 사용됩니다.
비동기 작업으로 함수가 종료되고 난 후 작업이 끝나고 호출할 필요가 있는 클로져를 사용해야 할 때 탈출 클로저(Escaping Closure)가 필요합니다.

static func retrieveFeed(url: URLConvertible,
                      method: HTTPMethod,
                      parameters: Parameters?,
                      headers: HTTPHeaders?,
                      completion: @escaping ([Post]) -> Void) {
        
        Alamofire
            .request(url, method: method, parameters: parameters)
            .responseData(completionHandler: { response in
                switch response.result {
                case .success(let value):
                    do {
                        let result = try JSONDecoder().decode([Post].self, from: value)
                        completion(result)
                    } catch {
                        print(error)
                    }
                case .failure(let error):
                    print(error)
                }
            })
    }

 

@autoclosure

  • 파라미터가 없는 표현식을 클로저로 변환하는 키워드
  • 파라미터가 없는 클로저에 사용 e.g. ()->(), ()->Int

closure 파라미터에 대입할 내용을 일반 함수 파라미터처럼 입력

var value2 = 10

func test() {
    print("Test")
}

func autoclosure(_ arg1: String, _ arg2: @autoclosure () -> ()) {
    print(arg1)
    arg2()
}

autoclosure("arg1", print("Autoclosure"))
autoclosure("arg1", value2 += 10)
autoclosure("arg1", test())

// Autoclosure 파라미터에 일반 클로저 형태는 사용 불가
// autoclosure("arg1") {
//  print("Compile Error")
// }



/*
출력

arg1
Autoclosure
arg1
arg1
Test
*/

 

 

'Swift' 카테고리의 다른 글

[Swift] 타입캐스팅(Type Casting)  (0) 2019.07.22
[Swift] 타입체크(TypeCheck)  (0) 2019.07.22
[Swift] Closure - 2 (Capturing)  (0) 2019.07.22
[Swift] Closure - 1 (Basic)  (0) 2019.07.22
[Swift] 옵셔널(Optionals)  (0) 2019.07.22