본문 바로가기
Swift

[Swift] 클로저의 Escaping과 Capture List

by giop15 2023. 10. 24.
반응형

안녕하세요. 클로저를 공부하게 되면서 클로저의 Escaping과 Capture List에 대한 내용을 정리해보려고 합니다.

 

[클로저의 Escaping]

클로저의 escaping 이란 어떤 함수에서 인자 값으로 클로저를 전달을 받을 때 이 클로저가 함수가 종료된 후에도 클로저를 호출할 수 있는 경우에 escaping이라고 합니다.

func downloadImage(imageURL: URL, completionHandler: @escaping (UIImage?) -> Void) {
    let task = URLSession.shared.dataTask(with: imageURL) { data, response, error in
        if let data = data, let image = UIImage(data: data) {
            completionHandler(image)
        }
    }
    task.resume()
}

위는 이미지를 다운로드하는 downloagImage(imageURL: completionHandler:) 함수를 예를 들어보았습니다. 함수 내부에서는 URLSession 객체에 있는 dataTask 메서드를 이용하여 비동기 실행을 하고 있습니다. 이때 completionHandler가 호출이 되고 있는데, downloadImage 함수가 끝나도 completionHandler는 살아있어야 비동기 처리 후 호출이 가능합니다. 그래서 @escaping 키워드를 붙여서 탈출 클로저를 만들어야 합니다.

 

[클로저의 Capture List]

클로저의 캡처 리스트는 캡처된 외부 변수나 상수를 대괄호’[]’로 이용하여 목록을 나열한 리스트입니다. 이것은 클로저가 어떤 변수를 캡처하고 어떤 방식으로 사용하는지를 명시적으로 나열하는 역할을 합니다.

값 타입의 경우와 참조 타입의 경우에 대해서 예시를 들어보겠습니다.

 

값 타입인 구조체를 예를 들어보겠습니다.

struct Person {
    var name: String
}

var person: Person = Person(name: "James")

print("1. name = \(person.name)")
let closure: () -> Void = { [person] in
    print("2. name = \(person.name)")
}

person.name = "Mike"
print("3. name = \(person.name)")
closure()

// 1. name = James
// 3. name = Mike
// 2. name = James

이 예시에서, 캡처 리스트를 사용하여`person`이라는 외부 변수를 클로저 내부로 캡처했습니다. 이 클로저는 외부 `person`의 값을 복사하여 저장하므로, 외부에서 `person`의 값이 변경되어도 클로저 내부에 영향을 주지 않습니다.

이것은 값 타입의 변수가 캡처 리스트를 통해 캡처될 때 발생하는 동작입니다. 캡처 리스트는 클로저와 외부 변수 간의 독립성을 유지하는 데 도움을 줍니다.

이번에는 참조 타입인 클래스를 예를 들어보겠습니다.

class Person {
    var name: String
    
    init(name: String) {
        self.name = name
    }
}

var person: Person = Person(name: "James")

print("1. name = \(person.name)")
let closure: () -> Void = { [person] in
    print("2. name = \(person.name)")
}

person.name = "Mike"
print("3. name = \(person.name)")
closure()

// 1. name = James
// 3. name = Mike
// 2. name = Mike

이 예시에서, 캡처 리스트를 사용하여 `person`이라는 외부 변수를 클로저 내부로 캡처했습니다. 이 클로저는 외부 `person`을 참조하고 있으며 외부에서 `person`의 값이 변경될 때 클로저 내부에서도 변경된 값을 사용합니다.

이것은 참조 타입 변수가 캡처 리스트를 통해 참조되어 외부 및 클로저 간에 동일한 인스턴스를 참조한다는 것을 보여줍니다.

 

지금까지 Swift의 클로저에서 escaping과 capture list에 대해서 살펴보았습니다.

반응형

'Swift' 카테고리의 다른 글

[Swift] 스위프트 메모리 관리  (1) 2023.10.26
[Swift] deinitializer 활용  (1) 2023.10.26
[Swift] 상수와 변수  (0) 2023.10.23