클로저는 스위프트에서 매우 강력하고 유용한 개념입니다. 이전에는 클로저 속에서 외부 범위의 변수나 상수에 대한 접근이 자유로웠지만, 스위프트 3에서부터는 접근 제어를 통해 클로저 내부에서 외부 변수에 접근하는 규칙을 정할 수 있게 되었습니다.
클로저에서 외부 변수 접근
클로저는 기본적으로 자신의 정의된 범위 내에서 선언된 변수나 상수에 접근할 수 있습니다. 이를 클로저 캡처링(capturing values) 이라고 합니다. 예를 들어, 아래의 코드에서 클로저는 total
이라는 변수에 접근하고 값을 변경합니다.
var total = 0
let increment: () -> Void = {
total += 1
}
increment()
print(total) // 1
위의 예제에서, 클로저는 외부 변수인 total
에 접근하여 값을 변경합니다. 따라서 클로저 외부에서 increment()
를 호출하면 total
의 값이 증가됩니다.
클로저에서의 접근 제어 설정
하지만, 때로는 외부 변수에 대한 접근을 제한하고 싶을 수도 있습니다. 스위프트에서는 접근 제어를 설정하여 클로저 내부에서 외부 변수에 접근하는 규칙을 제어할 수 있습니다.
@escaping
을 이용한 외부 변수 접근
@escaping
은 클로저가 외부 범위에서 사용될 때 클로저 내부에서 외부 변수에 접근할 수 있도록 해주는 특성입니다. 기본적으로 함수나 메소드에서는 클로저가 외부에서 사용되지 않아서 외부 접근이 허용되지 않습니다. 그러나 @escaping
키워드를 사용하여 클로저의 외부 접근을 허용할 수 있습니다.
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
func someFunction() {
var x = 10
let closure: () -> Void = {
print(x) // 외부 변수에 접근
}
someFunctionWithEscapingClosure(completionHandler: closure)
}
someFunction()
위의 예제에서, someFunctionWithEscapingClosure
함수는 @escaping
키워드를 사용하여 클로저를 외부에서 사용할 수 있도록 합니다. 클로저인 closure
는 외부 변수 x
에 접근하고 있습니다.
@noescape
를 이용한 외부 변수 접근
반대로 @noescape
키워드는 클로저가 외부 범위에서 사용되지 않을 때 클로저 내부에서 외부 변수에 접근을 제한하는 특성입니다. 기본적으로 함수나 메소드에서는 클로저가 외부에서 사용되지 않아서 접근이 제한됩니다. 그러나 @noescape
키워드를 사용하여 클로저의 외부 접근을 제한할 수 있습니다.
var x = 10
func someFunctionWithNoEscapeClosure(closure: () -> Void) {
closure()
}
func someFunction() {
someFunctionWithNoEscapeClosure {
print(x) // 외부 변수에 접근
}
}
someFunction()
위의 예제에서, someFunctionWithNoEscapeClosure
함수는 @noescape
키워드를 사용하여 클로저가 외부에서 사용되지 않도록 합니다. 클로저 자체는 외부 변수 x
에 접근하고 있습니다.
결론
스위프트에서는 클로저 캡처링을 통해 클로저 내부에서 외부 변수에 접근할 수 있습니다. 그러나 접근 제어 설정을 통해 클로저의 외부 접근을 제한할 수도 있습니다. @escaping
키워드는 외부 범위에서 사용되는 클로저에 대해 외부 변수 접근을 허용하고, @noescape
키워드는 외부 범위에서 사용되지 않는 클로저에 대해 외부 변수 접근을 제한합니다. 따라서 클로저와 접근 제어 설정을 이용하여 프로그램을 더욱 효율적으로 개발할 수 있습니다.