gpt4 book ai didi

swift - 使用 Apple 的新 Combine 框架时如何防止强引用循环(.assign 导致问题)

转载 作者:搜寻专家 更新时间:2023-11-01 05:31:43 25 4
gpt4 key购买 nike

我不太明白如何在类中正确存储订阅者,以便它们持久存在但不阻止对象被取消初始化。这是对象不会取消初始化的示例:

import UIKit
import Combine

class Test {
public var name: String = ""

private var disposeBag: Set<AnyCancellable> = Set()

deinit {
print("deinit")
}

init(publisher: CurrentValueSubject<String, Never>) {
publisher.assign(to: \.name, on: self).store(in: &disposeBag)
}
}

let publisher = CurrentValueSubject<String, Never>("Test")

var test: Test? = Test(publisher: publisher)
test = nil

当我将 assign 替换为 sink(我在其中正确声明了 [weak self])时,它实际上确实正确地 deinit(可能因为 assign 以导致问题的方式访问 self

例如,在使用 .assign 时如何防止强引用循环?

谢谢

最佳答案

您可以将 .asign(to:) 替换为 sink,其中 [weak self] 在其闭包中阻止了内存循环。在 Playground 中尝试一下,看看有什么不同

final class Bar: ObservableObject {
@Published var input: String = ""
@Published var output: String = ""

private var subscription: AnyCancellable?

init() {
subscription = $input
.filter { $0.count > 0 }
.map { "\($0) World!" }
//.assignNoRetain(to: \.output, on: self)
.sink { [weak self] (value) in
self?.output = value
}

}

deinit {
subscription?.cancel()
print("\(self): \(#function)")
}
}

// test it!!
var bar: Bar? = Bar()
let foo = bar?.$output.sink { print($0) }
bar?.input = "Hello"
bar?.input = "Goodby,"
bar = nil

它打印

Hello World!
Goodby, World!
__lldb_expr_4.Bar: deinit

所以我们没有内存泄漏!

终于在 forums.swift.org 上有人做了一个不错的小东西

extension Publisher where Self.Failure == Never {
public func assignNoRetain<Root>(to keyPath: ReferenceWritableKeyPath<Root, Self.Output>, on object: Root) -> AnyCancellable where Root: AnyObject {
sink { [weak object] (value) in
object?[keyPath: keyPath] = value
}
}
}

关于swift - 使用 Apple 的新 Combine 框架时如何防止强引用循环(.assign 导致问题),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57980476/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com