📝

[Combine] CurrentValueSubjectの挙動確認

に公開
  • sinkはCurrentVlaueSubjectをretainするのか?
    • する
      • ので、subscriptionを管理しないとsourceも残る。
  • CurrentValueSubjectはdeinitされる場合にsinkのcompletionを呼ぶのか?
    • sinkが動いている限りCurrentValueSubjectはdeinitされないので、呼ばれない
  • CurrentValueSubjectに対してcompletionを送信した場合、sinkのcompletionは呼ばれるのか?
    • 呼ばれる
       - subscription treeが破棄されてresourceも解放される。

実験の残骸


private struct _Book: View {
  
  var body: some View {
    Text("")
      .onAppear {
        
        weak var _s: CurrentValueSubject<Int, Never>?
        var cancellable: AnyCancellable?
        
        let pointer = Unmanaged.passRetained(CurrentValueSubject<Int, Never>(0))
        _s = pointer.takeUnretainedValue()
        
        Task {
          
          let resource = Resource()
          
          cancellable = pointer
            .takeUnretainedValue()
            .sink(receiveCompletion: { c in
              print("completion \(c)")
            }, receiveValue: { [resource] v in 
              print("value: \(v)")
              withExtendedLifetime(resource, {})
            })
          
          print("1 weak: \(_s)")
          
          pointer.release()
          pointer.takeUnretainedValue().send(completion: .finished)
                                     
          Task {            
            print("2 weak: \(_s)")
            cancellable?.cancel()
            print("3 weak: \(_s)")
          }
        }
                
      }
  }
  
  private final class Resource {
    deinit {
      print("Resource deinit")
    }
  }
}

Discussion