首先,我想强调的是,根据Firebase Crashlytics,这个bug只涉及大约1% of the user base个.
我有一个包含许多heic图像的xcasset目录.
以下是加载和显示正常图像或模糊图像的代码.
// Original image
self.imageView.image = UIImage(named: "officeBackground")!
// Blurred image
self.imageView.image = AssetManager.shared.blurred(named: "officeBackground")
我使用一个管理器来缓存模糊的图像,这样我就不必每次显示它们时都重新生成它们.
final class AssetManager {
static let shared = AssetManager()
private var blurredBackground = [String: UIImage]()
func blurred(named: String) -> UIImage {
if let cachedImage = self.blurredBackground[from] {
return cachedImage
}
let blurred = UIImage(named: named)!.blurred()!
self.blurredBackground[from] = blurred
return blurred
}
}
最后是模糊代码
extension UIImage {
func blurred() -> UIImage? {
let ciimage: CIImage? = self.ciImage ?? CIImage(image: self)
guard let input = ciimage else { return nil }
let blurredImage = input.clampedToExtent()
.applyingFilter("CIGaussianBlur", parameters: [kCIInputRadiusKey: 13])
.cropped(to: input.extent)
return UIImage(ciImage: blurredImage, scale: self.scale, orientation: .up)
}
}
以下是我遇到的两种类型的车祸
- 具有CFAutorelease的CoreFoundation.Crashlytics提供了有关它的其他信息:
crash_info_entry_0:
*** CFAutorelease() called with NULL ***
- 具有递归渲染的CoreImage.Crashlytics还提供了有关它的其他信息:
crash_info_entry_0:
Cache Stats: count=14 size=100MB non-volatile=0B peakCount=28 peakSize=199MB peakNVSize=50MB
我发现所有用户之间唯一的共同点是,他们在崩溃时有30-150个内存(根据Firebase,如果这个信息可靠的话?).
在这一点上,我真的很无知.CoreImage/CoreFoundation在处理内存中的CIImage时似乎存在一个bug.
奇怪的是,因为我使用AssetManager缓存模糊的图像,我知道在崩溃期间,用户已经在RAM中有了可用的缓存版本,但是当使用缓存的图像设置UIImageView时,它会因为内存不足而崩溃(?!).为什么系统甚至试图分配内存来执行此操作?