SwiftUI List内TextField拖拽排序触发ID重复警告问题
警告触发原因
- 你在使用
ForEach($items)遍历绑定集合时,循环项是Binding<Word>类型的包装对象,而非原始Word值实例。代码中指定的标识路径\ .self.id,没有稳定指向被包装的底层Word模型的固定id。 - 拖拽重排行的过程中,SwiftUI为了实现过渡动画、维持输入焦点与绑定的关联,会临时生成多个指向同一个底层
Word实例的Binding包装对象。这些临时对象通过你指定的id路径取值时会返回同一个UUID,导致ForEach检测到集合内存在重复id,抛出警告。 - 替换为
Text控件时无警告,是因为此时遍历的是原始值类型数组items,没有Binding包装层,重排过程不会生成临时对象,每个Word实例的id始终唯一,不会触发重复id检测。
修复方案
核心是让ForEach直接追踪底层Word模型的唯一id,不要以临时生成的Binding包装对象作为标识取值来源,两种可用写法:
- 利用
Word已遵循的Identifiable协议,不手动指定id参数,SwiftUI会自动读取绑定包装的底层模型id作为唯一标识:
List { ForEach($items) { $item in TextField("item", text: $item.str) } .onMove(perform: move) .onDelete(perform: delete) }
- 若需要显式指定id路径,明确声明取绑定包装的原始值id,规避动态成员查找在标识比对阶段的异常:
List { ForEach($items, id: \.wrappedValue.id) { $item in TextField("item", text: $item.str) } .onMove(perform: move) .onDelete(perform: delete) }
两种写法均可完全消除重排时的警告,且不影响输入、拖拽、删除功能的正常运行,无需修改Word模型的现有定义。
内容的提问来源于stack exchange,提问作者thecanteen
相关产品推荐
相关产品推荐

