在调试App时打开Xcode内存图工具,发现有循环引用
由上图可得:
SectionTrace对象->SectionDayTracesGroupHeader对象->通过闭包ignore.context->SectionTrace对象
同样有
SectionTrace对象->SectionDayTracesGroupHeader对象->通过闭包evaluate.context->SectionTrace对象
即SectionTrace和SectionDayTracesGroupHeader对象被2条线牢牢锁住,无法被释放!
打开SectionDayTracesGroupHeader类,看一下
class SectionDayTracesGroupHeader:HeaderFooterViewRepresentable{
typealias HandleType = (Date)->()
//忽略、评定按钮的回调
var ignoreHandle:HandleType?
var evaluateHandle:HandleType?
}
那么它们是在哪里被赋值的呢?
答案是在我的某一个VC里,因为evaluate闭包实现比较复杂所以只看ignore闭包:
///返回指定Section的忽略处理闭包
private func getIgnoreHandleWith(section:Section)->(Date)->(){
return {date in
if let idx = section.index{
//TODO:只是本次删除,下次还会显示
self.form.remove(at: idx)
}
}
}
注意传入的参数section,它是从哪里来呢?
是在Section被创建的时候:
let section = SectionTrace("\(day.dateString)"){section in
//省略无关代码...
header.evaluateHandle = getEvaluateHandleWith(section: section)
header.ignoreHandle = getIgnoreHandleWith(section: section)
section.header = header
}
OK!很清楚了,我们犯的错误是:
将section通过参数传给了header的闭包,导致header拥有section;而section随后又去拥有header.
我们需要打破其中一条链路:
private func getIgnoreHandleWith(section:Section)->(Date)->(){
return {[unowned self,unowned section]date in
if let idx = section.index{
//TODO:只是本次删除,下次还会显示
self.form.remove(at: idx)
}
}
}
如上代码,我们将闭包中的section替换为弱引用,所以上面的引用循环不复存在:
可见,原来的双线锁死已变为单线串联,一切都变的很美好了 ;)