我有一组构成装饰器模式的类,以便我可以进行一些分层缓存。我有一个抽象类,它提供了图像的核心处理,并包含许多可覆盖的函数,其中实现可以添加它们各自的处理。
保存图像时,我有以下代码:
func cacheImage(_ key:String, image:UIImage?) {
if let image = image {
saveImage(key, image:image)
} else {
deleteImage(key)
}
backingCache?.cacheImage(key, image:image)
}
func saveImage(_ key:String, image:UIImage) {}
func deleteImage(_ key:String) {}
这是奇怪的地方。编译为Release时,此代码将生成EXC_BAD_ACCESS。使用Zombies跟踪它会显示消息在被解除分配后发送到UIImage实例。
如果我尝试通过使用Debug配置进行编译来获取更多信息,则EXC_BAD_ACCESS将停止发生。使调试非常困难。
我发现如果我添加print(...)
这样的语句:
func deleteImage(_ key:String) {
print("Abstract delete image")
}
EXC_BAD_ACCESS消失了。
我目前的理论是,如果没有print(...)
,Swift会积极地取消分配图像实例。我还记得读过有关Debug延迟ARC垃圾收集的内容,这可以解释为什么在调试中不会发生EXC_BAD_ACCESS。
我现在还发现将方法签名更改为:
open func deleteImage(_ key:String) {}
同时删除EXC_BAD_ACCESS。
任何人都可以更详细地解释EXC_BAD_ACCESS僵尸发生的原因吗?我不明白为什么一开始。