[英]Swift closure is still in memory after VC deinit is called
我有一個藍牙類,當一個 char 值更新為視圖控制器中的閉包(以及單例類中的相同閉包)時,它會通過。 當調用 VC deinit 時,在更新 char 值時仍在執行 VC 中的閉包。 我在 VC 中使用 [weak self] 作為閉包。 我希望能夠在取消初始化視圖時阻止調用此 VC 閉包。 但是我也不明白為什么單例中的其他回調在VC呈現后沒有被執行!
下面包含了 VC 中閉包的語法
bluetooth.updatedCharacteristicsValue { [weak self] char in
[weak self]
並不意味着可以丟棄閉包,它只是防止閉包保留VC(從而防止VC被取消)。
簡單地開始你的關閉:
guard let self = self else { return }
... 如果 VC 不再存在,則提前退出。
至於為什么 VC 提供的閉包被調用而單例中的閉包沒有被調用,聽起來您的藍牙類不理解多個“用戶”的概念。 誰最后注冊他們的回調就是被調用的那個。
一種使用方便的自注銷令牌處理您自己的觀察者注冊的方法:
class ObserverToken {
let id = UUID()
private let onDeinit: (UUID) -> ()
init(onDeinit: @escaping (UUID) -> ()) {
self.onDeinit = onDeinit
}
deinit {
onDeinit(id)
}
}
class BluetoothThing {
// Associate observers with the .id of the corresponding token
private var observers = [UUID: (Int) -> ()]()
func addObserver(using closure: @escaping (Int) -> ()) -> ObserverToken {
// Create a token which sets the corresponding observer to nil
// when it is deinit'd
let token = ObserverToken { [weak self] in self?.observers[$0] = nil }
observers[token.id] = closure
return token
}
func tellObserversThatSomethingHappened(newValue: Int) {
// However many observers we currently have, tell them all
observers.values.forEach { $0(newValue) }
}
deinit {
print("👋")
}
}
// I've only made this var optional so that it can later be set to nil
// to prove there's no retain cycle with the tokens
var bluetooth: BluetoothThing? = BluetoothThing()
// For as long as this token exists, updates will cause this closure
// to be called. As soon as this token is set to nil, it's deinit
// will automatically deregister the closure
var observerA: ObserverToken? = bluetooth?.addObserver { newValue in
print("Observer A saw: \(newValue)")
}
// Results in:
// Observer A saw: 42
bluetooth?.tellObserversThatSomethingHappened(newValue: 42)
// A second observer
var observerB: ObserverToken? = bluetooth?.addObserver { newValue in
print("Observer B saw: \(newValue)")
}
// Results in:
// Observer A saw: 123
// Observer B saw: 123
bluetooth?.tellObserversThatSomethingHappened(newValue: 123)
// The first observer goes away.
observerA = nil
// Results in:
// Observer B saw: 99
bluetooth?.tellObserversThatSomethingHappened(newValue: 99)
// There is still one 'live' token. If it is retaining the
// Bluetooth object then this assignment won't allow the
// Bluetooth to deinit (no wavey hand)
bluetooth = nil
因此,如果您的 VC 將其令牌存儲為屬性,則當 VC 消失時,令牌消失並且閉包將被取消注冊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.