Open make1a opened 5 months ago
这是我的使用代码
extension UIImageView {
@nonobjc
/// 设置网络图片的统一入口方法
/// - Parameters:
/// - source: 可以传入 String 或者 URL 类型, 必须
/// - placeholder: 占位图, 在列表上使用的时候, 推荐放一张图片作为占位使用
/// - size: 图片解码到内存之前,按照大小去解码图片,解决大图 OOM 的问题。在已知图片大小的情况下,强烈建议使用该参数
public func kfSetImage(
url source: Any?,
placeholder: UIImage? = nil,
size: CGSize = .zero,
options: KingfisherOptionsInfo? = nil,
completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil) {
guard let source = source else {
self.image = placeholder
return
}
if #available(iOS 14, *) {} else if completionHandler == nil {
setImageIos13(url: source, placeholder: placeholder)
return
}
var defaultOptions: KingfisherOptionsInfo = [
.scaleFactor(UIScreen.main.scale),
.cacheOriginalImage
]
if let options = options {
defaultOptions += options
}
guard let url = self.url(from: source) else {
self.image = placeholder
return
}
setImage(with: url, placeholder: placeholder, size: size, options: &defaultOptions, completionHandler: completionHandler)
}
private func setImage(
with url: URL,
placeholder: UIImage?,
size: CGSize,
options: inout KingfisherOptionsInfo,
completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)?) {
if #available(iOS 14, *) {
/// autolayout 取不到 size
/// 在已经获取到容器大小的情况下,强制开启ImageIO图片下取样
var size = size
if size == .zero {
size = self.bounds.size
}
// 获取合适大小的图片展示
if !url.absoluteString.contains("gif"), size != CGSize.zero {
options += [.processor(DownsamplingImageProcessor(size: size))]
}
} else if url.absoluteString.contains("format,webp") {
options += [.processor(WebPProcessor.default), .cacheSerializer(WebPSerializer.default)]
}
kf.setImage(with: url, placeholder: placeholder, options: options, completionHandler: completionHandler)
}
}
建议可以监测一下在下面的情况下这部分内存能不能被释放:
clearMemoryCache
public static func crashAmountMemory() -> Double {
let name = UIDevice.name
switch name {
case .unknown:
return Double(ProcessInfo.processInfo.physicalMemory) * 0.55
case .iPad2: return Double(275) * 1024 * 1024
case .iPad3: return Double(645) * 1024 * 1024
case .iPad4: return Double(585) * 1024 * 1024
case .iPadMini: return Double(297) * 1024 * 1024
case .iPadAir: return Double(697) * 1024 * 1024
case .iPadAir2: return Double(1383) * 1024 * 1024
case .iPhone4: return Double(325) * 1024 * 1024
case .iPhone4s: return Double(286) * 1024 * 1024
case .iPhone5: return Double(645) * 1024 * 1024
case .iPhone5s, .iPhone5c: return Double(646) * 1024 * 1024
case .iPhone6: return Double(645) * 1024 * 1024
case .iPhone6Plus: return Double(645) * 1024 * 1024
case .iPhone6s: return Double(1396) * 1024 * 1024
case .iPhone6sPlus: return Double(1392) * 1024 * 1024
case .iPhoneSE: return Double(1395) * 1024 * 1024
case .iPhone7: return Double(1395) * 1024 * 1024
case .iPhone7Plus: return Double(2040) * 1024 * 1024
case .iPhone8, .iPhone8Plus, .iPhoneXsMax: return Double(1364) * 1024 * 1024
case .iPhoneX, .iPhoneXs, .iPhoneXr: return Double(1392) * 1024 * 1024
case .iPhone11, .iPhone11Pro, .iPhone11ProMax: return Double(2068) * 1024 * 1024
default: return Double(ProcessInfo.processInfo.physicalMemory) * 0.55
}
}
ImageCache.default.memoryStorage.config.totalCostLimit = Int(DeviceChecker.crashAmountMemory() * 0.2)
如果能够通过 clearMemoryCache
释放的话,说明这部分内存的申请和持有都没有问题。除了 memory warning 触发(这个只能选择信任OS会在合适的时候给出)的 NSCache
的清理外,Kingfisher 自身也监听了切后台的通知,会在app切换到后台时清理掉这部分内存缓存。
设置更小的内存 cache size 以及手动去更多调用 clearMemoryCache
也都是可以采用的方法。
想咨询一下, 我正在进行 app 的内存诊断工作,通过instrument Mark Generation 内存断点排查增长的内存会有大量的内存堆积在
SessionDataTask
(如下图)。 搭配 Memory Graph 诊断的时候 dirty memory 有两块大额内存集中在IOSurface、Image IO, 是使用了DownsamplingImageProcessor ,内部的 ImageIO scale 图片产生的。 我无法分辨,这些 dirty memory是否是应该存在的。 当我app 达到内存预警水位的时候,如何释放一部分内存。因为我注意到SessionDataTask 这块内存似乎一直在增长,clearMemoryCache
无法清理这块内存。我描述一下业务场景, 这些内存残留是在进入一个直播间后, 退出房间在控制器都销毁的情况下还遗留的