如何在 Swift 5.5 中使用 List 中的新绑定?

Posted

技术标签:

【中文标题】如何在 Swift 5.5 中使用 List 中的新绑定?【英文标题】:How do I use the new binding in List with Swift 5.5? 【发布时间】:2021-07-30 13:02:48 【问题描述】:

我正在尝试 SwiftUI 3(或者更确切地说是 Swift 5.5)中的新功能,您可以在其中直接绑定到列表中的项目。 应该很简单,但是我看不懂。

Xcode 测试版 4。

我可以单击列表中的一个项目,从而激活 TextField。但是,输入一个字符后,TextField 会失去焦点。

简单示例,我尝试在 MAC 和 ios 上运行它,结果相同。

struct ContentView: View 
    
    @State private var items = ["Item A", "Item B", "Item C"]
   
    var body: some View 
        List ($items, id: \.self)  $item in
            TextField("EditItem", text: $item)
        
    

【问题讨论】:

您是在测试新的更新还是想用它解决您的编程问题? 永远不要使用 'id: \.self' 这是一个严重的错误 @malhal 为什么?如果你有一个可散列的唯一值,为什么它是一个“严重错误”? @jnpdx 它会导致内存泄漏,因为在状态更改后再次调用主体时,SwiftUI 无法识别匹配的数据。文档状态 ID 需要是数据的属性,因此它不应该是数据本身。 【参考方案1】:

您通过使用\.self 来识别ForEach 中的元素,因此当您直接编辑一个字符串时,它会因为它被更改而获得一个新的身份,然后SwiftUI 将其视为对象的删除并插入新的对象而不是现有对象的更新。

当我尝试使用符合 Identifiable 的结构时,它可以正常工作,因为 SwiftUI 可以使用 id 属性跟踪更改的对象。

struct Item: Identifiable 
    let id = UUID()
    var name: String


struct ContentView: View 
    @State private var items = [Item(name: "Item A"), Item(name:"Item B"), Item(name: "Item C")]

    var body: some View 
        VStack 
            List($items, id: \.id)  $item in
                TextField("EditItem", text: $item.name)
            
            Text(items.map(\.name).joined(separator: " : "))
        
    

请注意,这很可能与 SwiftUI 3.0 或任何测试版无关,但更多的是预期行为

【讨论】:

非常感谢,这完全有道理!

以上是关于如何在 Swift 5.5 中使用 List 中的新绑定?的主要内容,如果未能解决你的问题,请参考以下文章

Swift 5.5 并发:如何序列化异步任务以用 maxConcurrentOperationCount = 1 替换 OperationQueue?

如何使用 SwiftUI 按按钮移动到另一个视图 - swift 5.5

.task 崩溃 - Swift 5.5 (iOS 15 Beta 5)

将 async/await (Swift 5.5) 与 firebase 实时数据库一起使用

如何在循环中链接 Swift 中的 Promise?

Swift 5.5 新特性