2014-12-10 2 views
1

다른 클래스 함수를 변수로 저장하는 클래스가있는 경우 참조주기가 발생할 수 있습니까?함수가 변수로 저장되면 참조주기가 발생할 수 있습니까?

class ClassA { 

    var i = 0 

    func incrementI() { 
     i++ 
    } 
} 

class ClassB { 

    private var function:() ->() 

    init(function:() ->()) { 
     self.function = function 
    } 

    func someFunc() { 
     function() 
    } 
} 

난에 ClassB가 약한 또는 소유되지 가변 기능을 저장할 수 없기

때문에,이 원인 기준주기 수 있는가? 아니면 그냥 참조주기/함수에 대한 나의 가난한 이해를 반영합니까?

답변

1

참조주기는 정확히 이름에서 알 수 있습니다. 하나의 객체는 원래 객체를 참조하는 다른 객체를 참조합니다. 두 개 이상의 객체로 구성 될 수 있습니다.

블록 또는 클로저를 사용하여 참조주기를 만드는 것이 쉬운 이유는 클로저에서 자체 캡처는 클로저 객체가 자체에 대한 참조를 가지기 때문입니다. 참조주기가있는 것보다 자기가 클로저에 대한 참조를 가지고있는 경우. ClassB의 init에 클로저를 전달 했으므로 예제가 안전하다고 생각합니다. 즉, 클로저가 존재하지 않는 객체에 대한 참조를 가질 수 없어야 함을 의미합니다. 우리가 외부 참조가없는 1 개를 작성,이 예에서는

class ClassB { 

    ... 

    func setSomeFunc(function :()->()) { 
     self.function = function 
    } 

    func printSomething() { 
     print("Something") 
    } 
} 

... 

func test() { 
    var x1 = { 
     print("Do Nothing") 
    } 
    var b : ClassB = ClassB(x1) 
    var x2 = { 
     b.printSomething() 
    } 
    b.setSomeFunc(x2) 
} 

: 당신의 예는 방법으로 기능을했다 경우

는, 당신은 당신이 할 수 있기 때문에 문제가있는 것입니다.

[x1] 

그러면 x1을 참조하여 b를 만듭니다. 이 참조는 ClassB의 init에 추가되었습니다.

[b]->[x1] 

그런 다음 b를 참조하여 x2를 만듭니다. b는 x2 클로저에서 캡처됩니다. 이는 b에 대한 강력한 참조를 보유한다는 것을 의미합니다.

[x2]->[b]->[x1] 

이제 우리는 b에 새로운 함수 x2를 할당합니다. 그러면 b에서 x1까지 참조가 깨집니다.

[x2]->[b]-x->[x1] 

x2에 대한 참조로 바꿉니다.

[x2]->[b]-\ [x1] 
/\  | 
    \-------/ 

이제 알 수 있듯이 원형 (또는 주기적) 참조가 있습니다. 이 참조를 깨는 유일한 방법은 b의 함수 멤버를 다른 것을 참조하도록 설정하거나 x2의 캡처 된 b 값을 다른 것으로 설정하는 것입니다.

관련 문제