인프런 커뮤니티 질문&답변

왈티님의 프로필 이미지
왈티

작성한 질문수

성공적인 진짜 iOS 개발자 되기 [기초부터 실무까지]

27. Closure_3

Closure_3 Capture List에 참조 타입 값을 작성할 경우에도 deinit 실행되는 이유가 뭘까요?

작성

·

53

·

수정됨

0

import UIKit

class TestClass {}

class SomeClass {
    var a = 10
    var b = TestClass()
    
    func myFunc() {
        print(self.a)
    }
    
    lazy var myClosure1: (()->Void)? = {
        () -> Void in
        print(self.a)
    }
    
    lazy var myClosure2 = {
        [a] () -> Void in
        print(a)
    }
    
    lazy var myClosure3 = { [b] in
        print(b)
    }
    
    
    deinit {
        print("SomeClass deinit")
    }
}

var myClass1: SomeClass? = SomeClass()
var myClass2 = myClass1
var myClass3 = myClass1
var myClass4 = myClass1

myClass1?.myClosure1

myClass1?.myClosure1 = nil
myClass1?.myClosure2
myClass1?.myClosure3

myClass1 = nil
myClass2 = nil
myClass3 = nil
myClass4 = nil

위 코드에서 myClusore3 의 캡쳐 리스트엔 b를 작성했고, b는 클래스의 인스턴스로 참조타입으로 알고 있습니다.
이 때 위 코드를 실행하면 deinit이 실행되는데요. weak 키워드를 사용하지 않았는데도 deinit이 실행되는 이유가 있을까요?

답변 2

0

iOS Developer - 이정님의 프로필 이미지
iOS Developer - 이정
지식공유자

안녕하세요

 

nil을 줘도 없어지지 않게 되려면 서로 강한참조 상태가 되는 즉 순환참조 상태로 만들어야 됩니다.

그러기 위해서는 SomeClass도 클로저를 강하게 참조하고 있어야 하고

클로저도 SomeClass를 강하게 참조하고 있어야 합니다.

 

SomeClass에 다음처럼 프로퍼티를 만들고

    var c: TestClass?

매소드는 다음처럼 변경해 보세요

    lazy var myClosure3 = { [b] in

        print(b)

        self.c = b

    }

    

그리고 nil로 설정하기 전에 다음처럼 클로저를 실행시켜야 서로 강한참조를 하고 있는 상태가 되어 deinit이 호출 안되는걸 확인하실 수 있습니다.

        myClass1?.myClosure3()

 

0

안녕하세요, 인프런 AI 인턴입니다. 왈티님.

질문해 주신 내용과 관련하여 “Swift에서의 클로저와 ARC”에 대해 설명드리겠습니다.

Swift에서의 클로저와 ARC

Swift의 클로저는 강하게 참조하는 클로저와 약하게 참조하는 클로저의 두 가지가 있습니다. 강한 참조는 클로저가 그 객체를 계속 참조하여 메모리에서 해제되지 못하게 만드는 경우입니다. 반대로 약한 참조는 객체가 해제될 수 있도록 돕습니다. weak 키워드를 사용하지 않고도 deinit이 실행되는 이유를 이해하기 위해서는 강한 참조 사이클(Strong Reference Cycle)을 잘 이해해야 합니다.

클로저에서 캡쳐 리스트를 사용할 때, 클로저는 그 변수의 강한 참조를 유지하는 경우가 많습니다. 하지만 다음과 같은 경우, 강하게 참조하지 않아서 deinit이 호출될 수 있습니다.

예시 코드 분석

lazy var myClosure3 = { [b] in
    print(b)
}

위 코드에서 [b]는 클로저가 b를 캡쳐하지만 이 클로저는 SomeClass의 인스턴스의 속성(myClosure3)으로 잡혀 있습니다. 캡쳐된 b는 클로저 내에서 사용되므로, b에 대해 강한 참조가 일어나지 않습니다. 따라서, SomeClass 인스턴스의 모든 참조가 사라질 때 deinit이 호출됩니다.

관련 답변 링크

더 자세한 내용을 원하시면, 유사한 질문과 답변이 있는 다음 링크들을 추천해드립니다:
- 약한 참조를 할 경우 self에 ?를 붙여야 하는 이유?
- Closure에서의 개념 정리

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

왈티님의 프로필 이미지
왈티

작성한 질문수

질문하기