You need to enable JavaScript to run this app. SwiftUI列表滚动时行内@State状态丢失问题求助
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI列表滚动时行内@State状态丢失问题求助

问题原因
  • List视图的复用机制:SwiftUI的List本质是基于可复用单元实现的滚动列表,当某一行完全滚动出屏幕可视区域后,对应的行视图实例会被系统回收销毁,后续该行再次滑入屏幕时会重新初始化一个全新的行视图实例。
  • @State的生命周期限制:@State是SwiftUI专为视图内部私有状态设计的属性包装器,它的存储完全绑定在对应的视图实例上,视图实例销毁时@State存储的所有数据也会同步释放。你当前把计数count定义为TestViewRow的内部@State,每次行视图重建时count都会被重置为初始值0,就出现了滚动后计数丢失的问题。
解决方案

推荐将行级状态和父层数据源绑定,利用父视图生命周期更长的特性持久化存储计数,修改后的代码如下:

  1. 首先定义承载条目内容和计数的数据源结构
struct ListItem: Identifiable {
    let id = UUID()
    let content: String
    var count: Int = 0
}
  1. 修改父视图,用绑定将数据源传递给子行视图
struct TestView : View {
    @State private var listItems:[ListItem] = (0..<50).map { ListItem(content: String($0)) }
    var body: some View {
        List($listItems) { $item in
            TestViewRow(item: $item)
        }
    }
}
  1. 修改子行视图,用@Binding接收状态,不再维护私有@State
struct TestViewRow: View {
    @Binding var item: ListItem
    
    var body: some View {
        HStack {
            Button(item.content, action: {
                item.count += 1
            })
            Text(String(item.count))
            Spacer()
        }
    }
}

这种方案下计数存储在父视图的@State数据源中,不会因为子行视图的复用销毁丢失,滚动后状态可以正常保留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 06:57:00