我有一个“updateBlocks”(闭包)数组,在单例类中使用它在数据更新时通知任何观察者(UIViewControllers等)。
我想知道移除观察者的最佳方法是什么,这样当观察者被释放(或者不再需要更新)时,它就不会被执行。
这是我当前的设置:
MySingleton类
var updateBlock: (() -> ())? {
didSet {
self.updateBlocks.append(updateBlock!)
self.updateBlock!() // Call immediately to give initial data
}
}
var updateBlocks = [() -> ()]()
func executeUpdateBlocks() {
for block in updateBlocks {
block()
}
}
MyObserver类
MySingleton.shared.updateBlock = {
...handle updated data...
}
MySingleton.shared.updateBlock = nil // How to properly remove???
最佳答案
你的单件设计有些问题。
将updateBlock
作为didSet方法的变量添加到updateBlocks
数组中是错误的设计。
我建议去掉updateBlock变量,而是定义一个addUpdateBlock
方法和一个removeAllUpdateBlocks
方法:
func addUpdateBlock(_ block () -> ()) {
updateBlocks.append(block)
}
func removeAllUpdateBlocks() {
updateBlocks.removeAll()
}
func executeUpdateBlocks() {
for block in updateBlocks {
block()
}
}
如果你想删除单个块,那么你需要一些方法来跟踪它们。正如rmaddy所说,每个街区都需要某种身份证。您可以重构容器,使块成为字典,并使用顺序整数键。添加新块时,addBlock函数可以返回键:
var updateBlocks = [Int: () -> ()]()
var nextBlockID: Int = 0
func addUpdateBlock(_ block () -> ()) -> Int {
updateBlocks[nextBlockID] = block
let result = nextBlockID
nextBlockID += 1
//Return the block ID of the newly added block
return result
}
func removeAllUpdateBlocks() {
updateBlocks.removeAll()
}
func removeBlock(id: Int) -> Bool {
if updateBlocks[id] == nil {
return false
} else {
updateBlocks[id] = nil
return true
}
func executeUpdateBlocks() {
for (_, block) in updateBlocks {
block()
}
如果将块保存在字典中,则它们不会按任何定义的顺序执行。