2017-11-15 13 views
1

참고 : 강력한 참조주기를 피하는 주제에 대한 (많은) 답변과 기사를 많이 읽었습니다. 그러나 이러한 사이클을 피하는 특정 부산물을 처리하는 방법에 대한 지침을 찾고 있습니다.Swift - 클로저 기반 구성에서 강력한 참조주기 피하기

다음 예제에서 Foo 클래스는 클로저를 사용하여 구성되도록 설계되었습니다. 클로저에 대한 참조는 나중에 사용하기 위해 캐시됩니다.

모델 데이터가 필요할 때마다 클로저가 호출됩니다. Foo가 제대로 작동하려면 데이터 이어야합니다.

class Foo 
{ 
    typealias ModelGetter = (() -> Model) 
    fileprivate var _modelGetter: ModelGetter! 

    ... 

    func configure(with modelGetter: @escaping ModalGetter) 
    { 
     _modelGetter = modelGetter 
    } 

    func printLastestModel() 
    { 
     // Get the latest model, do something with it. 
     precondition(_modelGetter != nil) 
     let model = _modelGetter() 
     print(model) 
    } 
} 

위 코드에서 _modelGetter는 암시 적으로 래핑되지 않습니다. Optional으로 정의 할 수 있지만 필요에 따라 래핑을 푸는 경우에도 Foo는 항상 제대로 작동하려면 클로저가 필요하므로 암시 적 언 래핑이 필요합니다.

푸의 인스턴스를 제작하고이를 구성 :

let foo = Foo() 
foo.configure(with: { self.makeModel() }) 
foo.printLatestModel() 

을하지만, 이것은 사이클을 유지 만듭니다.

그래서, [weak self]이 사용됩니다, 우리는 self의 선택성을 확인 :

foo.configure(with: { [weak self] in 
    guard let strongSelf = self else { return **WHAT** } 
    return strongSelf.makeModel() 
}) 

문제점이 자기가 nil이 될 수있다하더라도, 폐쇄 여전히를 반환해야한다는 요구

모델 (즉, 무엇?) 클로저의 호출자 (Foo 인스턴스). 그러나 self는 무효이므로 넘겨 줄 모델이 없습니다.

질문

누군가가이 상황에서 사용할 수있는 패턴을 추천 할 수 있습니까? 가급적이면 Foo가 modelGetter가 유효한지 여부를 확인하거나 Model이 유효한지 궁금하게 생각하지 않도록하고 싶습니다. Foo의 목적을 위해, Foo가 존재하면 항상 필요한 모델을 얻을 수 있어야합니다.

아니면 Foo의 요구를 재 설계해야 모델을 조달 할 수없는 가능성을 고려해야합니까? 어떤 도움을 주셔서 감사합니다.

답변

1

클래스가 Foo의 소유자 인 경우 [weak self] 대신 [unowned self]을 설정하는 것이 좋습니다. 문제를 해결할 것입니다. 한 클래스가 다른 클래스의 소유자 인 경우 문제가되지 않지만 논리가 잘못되면 프로젝트에서 무언가를 깨뜨린 것이 신호이기 때문에 잘못되지 않은 것으로 나타납니다.

+0

고맙습니다. 이 접근법을 취하고 프로그래머/설계 오류로 인한 모든 충돌을 처리합니다. – Womble

1

그러나 이것은 유지주기를 만듭니다.

아니요. foo은 클로저에 대한 참조를 소유하고 클로저는 self (분명히 foo이 아님)에 대한 참조를 소유합니다. selfFoo의 강력한 속성이 있고 foo으로 설정 한 경우 보유 주기만 유지됩니다.당신이 그렇게 가고있는 가정에

, 나는 두 가지 패턴 중 하나를 사용합니다 :

  • 내가 self 항상 foo의 평생있을 것 프로그래머로 가정합니다. 이 경우 [weak self] 대신 [unowned self]을 사용합니다. 내 가정이 잘못된 것으로 판명되면 프로그램이 중단되고 스택 추적을 기반으로 버그를 수정할 수 있습니다. 분명히, 당신은 꽤 광범위한 테스트 스위트가 가능한 한 가정을 검증하기를 원할 것입니다.

  • 내가 self 당신이 실종 처리하는 방법에 대한 세 가지 선택 사항이있는 경우 사라질 때까지가 유효한지 결정 :

    • 이 옵션 폐쇄 즉 () -> Model?의 반환 유형을 확인하고의 Foo이 가능하기를 nil 모델
    • selfnil 인 경우 반환하는 기본값은 Model입니다.
    • selfnil 인 경우 닫히고 오류가 발생하도록 선언합니다.

는 내가 아마 [unowned self]로 가서 반드시 내가 명시 적으로 어딘가에 강한 참조를 유지 할 거라고 생각합니다.

+0

Jeremy 고맙습니다. 나는 예 르케 블란 (Yerkebulan 's)의 충고를 받아 들일 것이며, [소유되지 않은 자아] 노선으로 갈 것입니다. 건배. – Womble