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

如何在SwiftData中实现列表懒加载?现有代码未按需加载

SwiftData列表懒加载问题及修复方案

问题说明

原本预期SwiftData支持列表懒加载,但通过Instruments检测发现,示例代码在视图出现时会一次性获取全部4200条Post数据,并未实现懒加载。

原代码

import SwiftUI
import SwiftData

@main
struct testappApp: App {
    var sharedModelContainer: ModelContainer = {
        let schema = Schema([
            Post.self,
        ])
        let modelConfiguration = ModelConfiguration(schema: schema)

        do {
            return try ModelContainer(for: schema, configurations: [modelConfiguration])
        } catch {
            fatalError("Could not create ModelContainer: \(error)")
        }
    }()

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(sharedModelContainer)
    }
}

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var posts: [Post]
    
    var body: some View {
        List {
            ForEach(posts) { post in
                Text(post.title)
            }
        }
        // Uncomment for initial posts creation
//        .onAppear {
//            for i in 0..<4200 {
//                let post = Post(title: "Post \(i)")
//                modelContext.insert(post)
//            }
//        }
    }
}

@Model
final class Post {
    var title: String
    
    init(title: String) {
        self.title = title
    }
}

检测截图

Instruments检测到一次性加载全部数据

修复方案

问题核心在于@Query返回的[Post]数组会触发全量数据加载,改用SwiftData提供的FetchedResults<Post>类型即可实现懒加载,该类型会根据列表滚动按需加载可见区域的数据。

修改后的ContentView代码:

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    // 将查询结果类型改为FetchedResults<Post>
    @Query private var posts: FetchedResults<Post>
    
    var body: some View {
        List {
            ForEach(posts) { post in
                Text(post.title)
            }
        }
        // Uncomment for initial posts creation
//        .onAppear {
//            for i in 0..<4200 {
//                let post = Post(title: "Post \(i)")
//                modelContext.insert(post)
//            }
//        }
    }
}

关键要点

  • FetchedResults是SwiftData专为懒加载设计的集合类型,遵循RandomAccessCollection协议,可直接用于ForEach遍历。
  • 列表滚动时,SwiftUI会自动触发FetchedResults加载当前可见项对应的数据,避免一次性加载全量内容。
  • 若需要添加排序、过滤条件,可直接在@Query参数中配置,不影响懒加载效果,例如:
    @Query(sort: \Post.title) private var posts: FetchedResults<Post>
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 06:05:11