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

时间:2020-07-05 13:59:28

标签: swift swiftui

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

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
            }
        }
    }
}

我不了解removeRows(at offsets: IndexSet)的{​​{1}}自定义函数处理程序是如何工作的。具体来说,为什么在.onDelete()之前有一个参数标签at。例如,您可以使用offsets:而不是on吗?参数标签是否只是为了我们更好地理解代码?

然后有一个at,我认为我可以理解为一种类型,该类型持有一个用于索引目的的Int或用于删除列表中某行的Int范围,以便swiftui知道要删除哪一行?

我想我了解IndexSet实际上是用来删除numbers.remove(atOffsets: offsets)上的列表行的(根据实际的行索引被删除)-但我不确定{{ 1}}实际上是迅速知道的吗?到底是什么offsets,它的值如何设置?

我正在尝试通过遵循this来学习。我仍然对swiftui有非常基础的知识,所以请像我这样超级菜鸟来解释一下。

1 个答案:

答案 0 :(得分:1)

如果您查看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)期望IndexSet标签使用atOffsets参数(并且您不能更改此标签),但是您可以根据需要随意命名参数:

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