V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
qtoq126
V2EX  ›  iDev

一个简简单单的 ScrollView+LazyVGrid,就出现滚动卡顿了

  •  
  •   qtoq126 · 3 天前 · 1833 次点击
    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)
                    }
                }
            }
        }
    }
    

    实现的是一个日期的下面,展示这个日期内所有发布的 works ,如:

    2024 年 10 月 10 日
    work1, work2, work3
    work4, work5, work6
    2024 年 9 月 10 日
    work5, work6, work7
    work8, work9, work10

    work 都是按照 LazyVGrid 布局的

    我真机调试的时候,很明显的发现滚动到一定位置然后往回滚的时候,会出现卡顿,滚一段距离必定卡一下,是必现的,不知道原因在哪里

    18 条回复    2025-04-01 00:15:09 +08:00
    hwdq0012
        1
    hwdq0012  
       3 天前
    scrollview 一般表示无限空间吧, 里面再放个自动扩张的容器,那就变成无限扩张了
    一般都会有个虚拟化技术只渲染控件看得到的区域多一点的数据

    我不会 h5,但纵观微软 wpf, qt 都是如此
    superkeke
        2
    superkeke  
       3 天前
    用 tableview
    DLOG
        3
    DLOG  
       3 天前
    用 UICollectionView , cell 复用
    项目上基本不会用到 ScrollView
    Uyloal
        4
    Uyloal  
       3 天前   ❤️ 1
    KFImage(URL(string: workImageCover)) 加个 .aspectRatio(504 / 320, contentMode: .fit) 试试,卡顿感应该是来自于图片实际高度和预测高度不一致,导致 ScrollView ContentSize 在变化
    holy_sin
        5
    holy_sin  
       3 天前
    swiftUI 处理动态大小 cell 确实坑
    vvard3n
        6
    vvard3n  
       3 天前
    ScrollView 没有复用机制,用 List 吧
    kele999
        7
    kele999  
       3 天前
    加载数据的时候卡一下正常的
    qtoq126
        8
    qtoq126  
    OP
       3 天前
    @kele999 我的图片已经都已经缓存了,不需要在加载,都是单纯的滚动卡顿
    iOCZS
        9
    iOCZS  
       3 天前
    lazy 对滚动并不友好,我宁愿初期白一下,后面滚动流畅,而不是快速展示,滚动的时候卡卡的。
    MacsedProtoss
        10
    MacsedProtoss  
       3 天前 via iPhone
    这是没写过 uikit 的情况下直接写 swiftui ?正常应该没啥人会用 scrollview 写这种场景的
    qtoq126
        11
    qtoq126  
    OP
       3 天前
    @MacsedProtoss 没学过 uikit ,直接上手的 swiftui ,请问下 swiftui 下这种布局一般如何实现呢?
    qtoq126
        12
    qtoq126  
    OP
       3 天前
    @iOCZS 在 swiftui 下,有哪些更好的解决办法?
    okakuyang
        13
    okakuyang  
       3 天前
    你写的实际上没什么问题,swiftUI 的滚动视图比较抽象,它不像老的 UIkit 里面的 Api 定义的那么清晰。如果你想要更好的表现,可以考虑优化这个问题。

    1. 图片解码时间优化
    2. 第三方图片加载库与 swiftui 的兼容性问题
    3. 动态计算 cell 大小问题
    4. section 可能导致的布局问题
    5. LazyVGrid 的 cell 缓存优先度
    6. swiftui 不同版本的表现差异
    7. 真机性能限制问题
    keepro
        14
    keepro  
       3 天前
    是这个服务 SysMain (维护和提高一段时间内的系统性能。)导致的,以前遇到过,查了很久。
    keepro
        15
    keepro  
       3 天前
    @keepro #7 发错贴了,对不住
    magic3584
        16
    magic3584  
       3 天前
    看你近期帖子都是 SwiftUI , 建议抛弃改用 UIKit
    AlwaysBee
        17
    AlwaysBee  
       3 天前   ❤️ 1
    @Uyloal @qtoq126 #4
    这个是正解
    qtoq126
        18
    qtoq126  
    OP
       2 天前
    @Uyloal
    @AlwaysBee
    赞一个,确实如此,固定了尺寸后就好了,丝滑无比,感谢大佬们
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2444 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 284ms · UTC 15:17 · PVG 23:17 · LAX 08:17 · JFK 11:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.