iOS一直讲的单元格优化
1 复用Cell(dequeueReusableCellWithIdentifier:);
2 异步解码图片、离屏渲染(如使用CATiledLayer);
3减少AutoLayout计算,预计算Cell高度;
4 使用willDisplayCell延迟加载非关键资源
异步解码图片、离屏渲染(如使用CATiledLayer)这两个之前没有开发过,今天写一个demo记录一下
/*异步解码图片,避免单元格卡顿当你用 UIImage(named:) 或 UIImage(data:) 加载图片时,系统会延迟解码(lazy decode):• 图片只在真正显示到屏幕上时才会解码。• 解码操作发生在主线程上 → 容易造成 UI 卡顿(掉帧)。*/
class DecodeImages {//可以结合 DispatchSemaphore 控制并发,避免同时解码过多大图导致内存暴涨//信号量限制最大解码数量为2let semaphore = DispatchSemaphore(value: 2)let queue = DispatchQueue(label: "www.baidksk.com",attributes: DispatchQueue.Attributes.concurrent)func asyncDecodeImage(_ data: Data, complete: @escaping (UIImage?)->Void) {semaphore.wait()defer {semaphore.signal()}guard let imageSource = CGImageSourceCreateWithData(data as CFData, nil),let cgImage = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) else {DispatchQueue.main.async {complete(nil)}return}let decodedImage = UIImage(cgImage: cgImage,scale: UIScreen.main.scale,orientation: .up)DispatchQueue.main.async {complete(decodedImage)}}}
/*当一张超大图(如地图、PDF、超高清图)显示在 UIScrollView 或 CALayer 上时,如果一次性全部解码、渲染,会非常消耗内存。解决思路使用 CATiledLayer 分块(tile)绘制:系统只绘制当前可见区域的部分图块,每块独立解码与渲染。• CATiledLayer 自动多线程渲染;• 每个 tile 的渲染在后台进行;• iOS 系统内部使用 GCD 调度线程;• 你可以通过 DispatchSemaphore 控制最大渲染任务数量,以防 GPU/CPU 占用过高。*/class OutScreenRenderView : UIView {private let image: CGImageoverride class var layerClass: AnyClass {CATiledLayer.self}init(image: CGImage) {self.image = imagesuper.init(frame: .zero)let titleLayer = self.layer as! CATiledLayertitleLayer.levelsOfDetail = 4titleLayer.tileSize = CGSize(width: 256, height: 256)contentScaleFactor = 1.0}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}override func draw(_ layer: CALayer, in ctx: CGContext) {let rect = ctx.boundingBoxOfClipPathlet scale = layer.contentsScalelet imageRect = CGRect(x: 0, y: 0, width: CGFloat(image.width), height: CGFloat(image.height))ctx.saveGState()ctx.translateBy(x: 0, y: imageRect.size.height)ctx.draw(image, in: rect)ctx.restoreGState()}
}