SwiftUI列表中的onDelete()函数处理程序如何工作?

6

我了解以下代码可以工作:

struct ContentView: View {
    func removeRows(at offsets: IndexSet) {
        numbers.remove(atOffsets: offsets)
    }
    
    @State private var numbers = [Int]()
    @State private var currentNumber = 1

    var body: some View {
        VStack {
            List {
                ForEach(numbers, id: \.self) {
                    Text("\($0)")
                }
                .onDelete(perform: removeRows)
            }

            Button("Add Number") {
                self.numbers.append(self.currentNumber)
                self.currentNumber += 1
            }
        }
    }
}

我不明白的是 .onDelete() 自定义函数处理程序中的 removeRows(at offsets: IndexSet) 如何工作。特别是,为什么在 offsets: 前面有一个关键字 at。例如,可以使用 on 吗?这个参数标签只是为了让我们更好地理解代码吗?
然后还有 IndexSet,我认为它是一种用于索引的 Int 类型或用于在列表中删除行的 Int 范围类型,以便 SwiftUI 知道要删除哪一行。
我认为我理解 numbers.remove(atOffsets: offsets) 是用于实际删除 offsets 中的列表行(就被删除的实际行索引而言)- 但我不确定 Swift 如何知道 offsets 的值?实际上,offsets 是什么,它的值如何设置?
我正在尝试通过遵循这个来学习。我对 SwiftUI 只有非常基本的了解,请像我完全不懂一样解释。

请参阅函数参数标签和参数名称 - pawello2222
谢谢@pawello2222,我意识到这回答了我的关于参数标签的问题。我假设swift.org文档意味着我们可以使用任何单词作为参数标签,而不是at?(我发现swift.org上的解释对我来说不够明确)。但我仍然对我的其他问题感到困惑。 - Super Noob
1个回答

8

如果你查看onDelete的签名:

@inlinable public func onDelete(perform action: ((IndexSet) -> Void)?) -> some DynamicViewContent

你可以看到它期望一个类型为((IndexSet) -> Void)?的参数。

这意味着它需要一个接受IndexSet参数并返回Void的函数。

你的removeRows函数正好与所需类型相同:

func removeRows(at offsets: IndexSet) { ...

*上述签名等同于:

func removeRows(at offsets: IndexSet) -> Void { ...

标签at是为了清晰而使用的,它也可以被称为someCustomLabel:

func removeRows(someCustomLabel offsets: IndexSet) { ...

但是你需要这样调用它:

removeRows(someCustomLabel: indexSet)

您可以完全跳过标签:
func removeRows(offsets: IndexSet) { ...

并且这样调用你的函数:
removeRows(offsets: indexSet)

请注意:
.onDelete(perform: removeRows)

等同于:

.onDelete(perform: { indexSet in
    self.removeRows(at: indexSet)
})

IndexSet 指定要删除的索引。当您在 List 中向左滑动一行时,它将调用 onDelete 函数,并将行索引传递给 IndexSet 参数。

请注意,numbers.remove(atOffsets: offsets) 期望使用 atOffsets 标签的 IndexSet 参数(您无法更改此标签),但您可以自由命名参数:

func removeRows(at indexSetToDelete: IndexSet) {
    numbers.remove(atOffsets: indexSetToDelete)
}

谢谢@pawello2222,这很有帮助。只是为了明确,当你提到 indexSet 时,你是否意味着键入 IndexSet?此外,这是否意味着当用户向左滑动行以调用 onDelete 函数时,Swift 会自动将该行索引发送到 IndexSet 参数 (offsets) 中?这是否是 onDelete 函数自动执行的无需我担心的事情?此外,确认一下,IndexSet 是参数 offsets 的值类型,对吗? - Super Noob
1
@SuperNoob IndexSet 是一个 类型。在 .onDelete(perform: { indexSet in ... 中,indexSet 是某个值。在 Swift 中,惯例是对类型使用大写字母。是的,在滑动删除时会自动调用 onDelete 函数。它将给你一些行的集合,你可以决定要做什么。我建议你阅读更多关于 函数 的 Swift 文档。 - pawello2222

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接