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

SwiftUI iOS15 Bug:List刷新动作执行于旧视图实例,求解决方案

解决SwiftUI中refreshable无法获取视图最新参数的问题

问题描述

在SwiftUI中给List添加refreshable修饰符后,当List所在的子视图(TestChildView)因父视图传入的参数更新而重新实例化时,下拉触发的刷新动作仍然会使用旧视图实例的参数值,无法获取当前最新的参数。例如点击递增按钮后,列表内容已更新为新的参数值,但下拉刷新时打印的还是初始值。

解决方案

方法1:使用.id()强制视图完全重建

在父视图中给TestChildView添加.id(myVar)修饰符,让参数变化时子视图被完全销毁并重新创建,确保refreshable闭包绑定到最新的参数值:

struct TestParentView: View {
    @State var myVar = 0

    var body: some View {
        VStack {
            Text("increment")
                .onTapGesture {
                    myVar += 1
                }
            TestChildView(myVar: myVar)
                .id(myVar) // 添加这一行
        }
    }
}

方法2:子视图内部维护同步状态

在子视图中用@State变量同步父视图传入的参数,让refreshable闭包捕获这个可变的状态变量,确保能获取最新值:

struct TestChildView: View {
    let myVar: Int
    @State private var currentMyVar = 0 // 新增内部状态
    
    struct Item: Identifiable {
        var id: String { val }
        let val: String
    }

    var list: [Item] {
        [Item(val: "a \(myVar)"), Item(val: "b \(myVar)"), Item(val: "c \(myVar)")]
    }
    
    var body: some View {
        VStack {
            List(list) { elem in
                Text(elem.val)
            }.refreshable {
                print("myVar: \(currentMyVar)") // 使用内部状态
            }
        }
        .onChange(of: myVar) { newValue in
            currentMyVar = newValue // 参数变化时更新内部状态
        }
        .onAppear {
            currentMyVar = myVar // 初始化时同步参数
        }
    }
}

问题原因

SwiftUI的refreshable修饰符通过设置环境中的刷新动作实现,当视图因参数更新重新计算body时,旧视图实例的刷新动作并未被替换,导致闭包捕获的仍是旧的参数值。两种解决方案分别通过强制视图重建或绑定可变状态变量,让刷新闭包能获取到最新的参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:55:44