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

SwiftUI List中使用ScrollViewReader滚动时崩溃问题求助

解决SwiftUI List结合ScrollViewReader滚动时的崩溃问题

问题原因

在iOS 16 + Xcode 14.0.1环境下,使用ScrollViewReader的scrollTo(_:)方法滚动到List中新添加的条目时,会触发EXC_BAD_INSTRUCTION崩溃。这是因为List更新视图的时机与scrollTo调用时机不匹配:当我们设置scrollItem并触发滚动时,List还未完成新条目的视图渲染与ID注册,导致ScrollViewProxy找不到对应的视图ID,进而引发崩溃。

修复方案

以下是几种可行的修复方式,任选其一即可:

方案1:异步延迟执行scrollTo

修改onChange的回调逻辑,通过DispatchQueue.main.async将滚动操作延迟到主队列空闲时执行,确保List已完成视图更新:

.onChange(of: scrollItem) { newValue in
    DispatchQueue.main.async {
        proxy.scrollTo(newValue)
    }
}

方案2:在Task中异步设置scrollItem

修改addItem方法,通过@MainActor的Task异步设置scrollItem,等待List完成数据源更新后的视图渲染:

func addItem() {
    items.append(Item())
    Task { @MainActor in
        scrollItem = items.last?.id
    }
}

方案3:监听items变化而非scrollItem

直接监听数据源items的变化,当有新条目添加时,异步执行滚动操作:

List {
    ForEach(items) { item in
        Text(item.id.uuidString)
            .id(item.id)
    }
}
.listStyle(.inset)
.onChange(of: items) { _ in
    guard let lastId = items.last?.id else { return }
    DispatchQueue.main.async {
        proxy.scrollTo(lastId)
    }
}

这种方式可以去掉scrollItem这个状态变量,简化逻辑。

说明

以上方案均通过调整滚动操作的执行时机,确保ScrollViewProxy能找到已注册的视图ID,从而避免崩溃。同时保留了List原生的滑动删除功能,满足实际项目需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 01:41:03