본문 바로가기

Swift/공식문서

[Swift 공식문서 번역] ARC (Automatic Reference Counting) - 5. (마지막)

 

ARC 공식문서에서 마지막 파트,,

 

Defining a Capture List

Weak and Unowned References

마무리 지어보겠습니당

캡처 리스트와 약한/미소유 참조 스따뜨!

 

 

약간의 의역이 포함될 예정이니 오역이나 업데이트가 필요한 부분은 꼭 댓글로 알려 주시와요

 

 

 

 

 

 

 

Defining a Capture List (캡처 리스트 정의하기)

캡처 리스트의 각 요소는 weak나 unowned 키워드와 클래스 인스턴스(self와 같은), 혹은 어떠한 값으로 초기화된 변수(delegate = self.delegate 같은)로 이루어진 한 쌍입니다. (weak/unowned & 인스턴스/변수 꼴의 한 쌍이라는 말) 이 쌍들은 대괄호 안에 컴마로 구분하여 작성합니다.

 

클로저에 파라미터 리스트와 리턴 타입이 있다면, 그 앞에 캡처 리스트를 작성하세요:

lazy var someClosure = {
    [unowned self, weak delegate = self.delegate]
    (index: Int, stringToProcess: String) -> String in
    // 클로저 바디 부분은 이 곳에 작성
}

 

 

클로저가 컨텍스트로부터 파라미터 리스트나 리턴 타입을 추론할 수 있어서 명시할 필요가 없다면, 캡처 리스트를 클로저의 가장 앞 부분에 작성하고 그 뒤에 in 키워드를 작성합니다:

lazy var someClosure = {
        [unowned self, weak delegate = self.delegate] in
    // 클로저 바디 부분은 이 곳에 작성
}

 

 

 

 

 

 

Weak and Unowned References (약한 참조와 미소유 참조)

클로저와 그 클로저가 캡처하는 인스턴스가 항상 서로를 참조하고, 항상 동시에 메모리 해제가 될 경우에는, 클로저에서 캡처를 미소유 참조로 정의하세요.

 

반대로, 캡처한 참조가 언젠가 nil이 될 수도 있다면 캡처를 약한 참조로 정의하세요. 약한 창조는 항상 옵셔널 타입이고, 참조하는 인스턴스가 메모리에서 해제되면 자동으로 nil이 됩니다. 이것으로 클로저 바디 안에서 존재 여부를 확인할 수 있죠.

 

주의
캡처한 참조가 절대 nil이 되지 않을 것이라면, 약한 참조가 아니라 항상 미소유 참조로 캡처되어야 합니다.

 

 

미소유 참조는 Strong Reference Cycles for Closures (클로저의 강한 순환참조)의 HTMLElement 예시에서 보았던 강한 순환참조를 해결하기 위한 적절한 캡처 방법입니다. 순환을 피하기 위해서는 HTMLElement 클래스를 이렇게 작성하면 됩니다:

 

class HTMLElement {


    let name: String
    let text: String?


    lazy var asHTML: () -> String = {
            [unowned self] in
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }


    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }


    deinit {
        print("\(name) is being deinitialized")
    }


}

 

이 HTMLElement 구현 방식은 asHTML 클로저 안에 캡처 리스트를 추가한 것 이외에는 기존의 구현 방식과 동일합니다. 여기서는 캡처 리스트가 [unowned self] 인데, 이것은 "self를 강한 참조가 아니라 미소유 참조로 캡처한다"는 뜻입니다. 

 

 

전처럼 HTMLElement 인스턴스를 프린트해 보면:

var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
// "<p>hello, world</p>" 출력

 

위 코드의 캡처 리스트가 적용된 참조는 다음과 같은 모습입니다:

 

 

이번에는 클로저의 self 캡처가 미소유 참조고, 클로저가 캡처한 HTMLElement 인스턴스를 강하게 붙잡지 않습니다. paragraph 변수가 가지는 강한 참조를 nil로 설정하면, HTMLElement 인스턴스는 메모리에서 해제되고, 아래 예시에서처럼 디이니셜라이저 메시지 출력으로 확인할 수 있습니다.

 

paragraph = nil
// "p is being deinitialized" 출력

 

캡처 리스트에 대한 더 많은 정보는 Capture Lists를 확인하세요.

 

 

 

 

 

 

캡처 리스트 문서도 번역해야겠군 ....