You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LazyVGrid与ScrollView滚动卡顿性能问题求助

真机滚动卡顿问题排查与优化方案

问题现象

真机调试时,滚动至特定位置后回滚出现明显卡顿,动画流畅度下降;替换Section为VStack后问题仍存在,但模拟器测试无异常。

问题代码

import SwiftUI
import Kingfisher

struct WorksDateView: View {
    
    let columns: [GridItem] = [
        GridItem(.flexible(), spacing: 8),
        GridItem(.flexible(), spacing: 8),
        GridItem(.flexible(), spacing: 8)
    ]
        
    var data: [DateWorksModel]
            
    var body: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 16) {
                ForEach(data) { item in
                    Section {
                        ForEach(item.works) { work in
                            NavigationLink(destination: WorkDetailView(workId: work.id)) {
                                WorksDateCell(
                                    workImageCover: work.imageCover,
                                    workId: work.id,
                                    actressName: work.actressName,
                                    actressAvatar: work.actressAvatar
                                )
                            }
                            .buttonStyle(PlainButtonStyle())
                        }
                    } header: {
                        Text(item.releaseDate)
                            .font(.title)
                            .fontWeight(.bold)
                            .frame(maxWidth: .infinity, alignment: .leading)
                            .padding(.top, 8)
                    }
                }
            }
            .padding(.horizontal)
        }
    }
}

struct WorksDateCell: View {
    
    var workImageCover: String = "https://fakeimg.pl/320x504/fe9a2b/000"
    var workId: String = "xxx"
    var actressName: String = "xxx"
    var actressAvatar: String = "https://fakeimg.pl/60x60/ff425a/100"
    var avatarSize: CGFloat = 30.0
    
    var body: some View {
        VStack(alignment: .leading) {
            KFImage(URL(string: workImageCover))
                .placeholder {
                    ProgressView()
                }
                .resizable()
                .scaledToFit()
                .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous))
            
            HStack {
                KFImage(URL(string: actressAvatar))
                    .placeholder {
                        ProgressView()
                    }
                .resizable()
                .scaledToFill()
                .frame(width: avatarSize, height: avatarSize)
                .clipShape(Circle())
                
                VStack(alignment: .leading) {
                    Text(workId)
                        .fontWeight(.medium)
                        .font(.subheadline)
                    Text(actressName)
                        .foregroundStyle(.secondary)
                        .font(.caption)
                        .lineLimit(1)
                }
            }
        }
    }
}

优化建议

1. 图片加载优化(Kingfisher)

图片加载是真机卡顿的核心诱因,需针对性优化:

  • 强制缓存原始图片,避免重复下载:给KFImage添加cacheOriginalImage()和diskCacheExpiration(.days(7))
  • 取消滑出屏幕的图片请求:添加.cancelOnDisappear(true),释放未完成请求的资源
  • 固定图片尺寸,避免动态布局计算:给封面图设置基于列宽的比例高度
// 修改后的WorksDateCell封面图部分
KFImage(URL(string: workImageCover))
    .placeholder { ProgressView() }
    .resizable()
    .scaledToFit()
    .frame(height: (UIScreen.main.bounds.width - 32)/3 * 1.58) // 适配3列布局的固定高度
    .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous))
    .cacheOriginalImage()
    .diskCacheExpiration(.days(7))
    .cancelOnDisappear(true)

2. 布局稳定性优化

  • 固定LazyVGrid列宽,避免布局波动:将GridItem(.flexible())改为带固定最小宽度的配置
let columns: [GridItem] = [
    GridItem(.flexible(minimum: (UIScreen.main.bounds.width - 32)/3 - 8), spacing: 8),
    GridItem(.flexible(minimum: (UIScreen.main.bounds.width - 32)/3 - 8), spacing: 8),
    GridItem(.flexible(minimum: (UIScreen.main.bounds.width - 32)/3 - 8), spacing: 8)
]
  • 避免提前初始化目标视图:将NavigationLink改为延迟加载模式(iOS16+可用navigationDestination)
// 修改后的WorksDateView结构
NavigationStack {
    ScrollView {
        LazyVGrid(columns: columns, spacing: 16) {
            ForEach(data) { item in
                VStack(alignment: .leading) {
                    Text(item.releaseDate)
                        .font(.title)
                        .fontWeight(.bold)
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .padding(.top, 8)
                    
                    ForEach(item.works) { work in
                        NavigationLink(value: work.id) {
                            WorksDateCell(
                                workImageCover: work.imageCover,
                                workId: work.id,
                                actressName: work.actressName,
                                actressAvatar: work.actressAvatar
                            )
                        }
                        .buttonStyle(PlainButtonStyle())
                    }
                }
            }
        }
        .padding(.horizontal)
    }
    .navigationDestination(for: String.self) { workId in
        WorkDetailView(workId: workId)
    }
}

3. 性能排查工具

用Xcode自带工具定位根因:

  • Core Animation Instrument:查看卡顿帧的耗时阶段(布局/渲染/IO)
  • Debug View Hierarchy:检查视图层级是否过深,有无冗余视图

内容的提问来源于stack exchange,提问作者Windy418

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 14:25:55