为什么包含范围运算符抛出错误,而独占运算符不会抛出错误?



我正在尝试使用ForEach在 SwiftUI 中构建选择器的选项,但范围运算符似乎没有像我预期的那样工作。

这是我的代码:

struct ContentView: View {
@State private var inputString = ""
@State private var inputUnits = 0
let units = ["Fahrenheit", "Celsius", "Kelvin"]
var body: some View {
Form {
Section(header: Text("Convert:")) {
TextField("Enter input", text: $inputString)
Picker("Unit", selection: $inputUnits) {
ForEach(0 ... 2) {
Text("(self.units[$0])")
}
}
}
}
}

}

编译器的...范围运算符存在问题。它抛出两个错误:

  1. 无法推断泛型参数"ID">
  2. "ForEach"上引用初始值设定项"init(_:content:("要求"Int"符合"可识别">

奇怪的是,..<运算符在这里工作正常,所以如果我改用这行代码,代码会编译:

ForEach(0 ..< 3) {

这对我来说似乎是一个错误,但是这些运算符之间是否存在我不知道的区别?

是的,有区别:

对于Range<Int>(..<(运算符,有显式扩展ForEach指定关联类型

@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension ForEach where Data == Range<Int>, ID == Int, Content : View {

而对于ClosedRange<Int>(...(则没有这样的,它被认为是更通用的集合

/// A structure that computes views on demand from an underlying collection of
/// of identified data.
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct ForEach<Data, ID, Content> where Data : RandomAccessCollection, ID : Hashable {

因此需要明确提供 ID 类型,如下所示

ForEach(0...2, id: .self) {

或者您可以声明自己的扩展

extension ForEach where Data == ClosedRange<Int>, ID == Int, Content : View {
public init(_ data: ClosedRange<Int>, @ViewBuilder content: @escaping (Int) -> Content) {
self.init(data, id: .self, content: content)
}
}

然后只需使用

ForEach(0...2) {

这是因为0 ... 2ClosedRange<Int>0 ..< 3Range<Int>

如果您在此处查看ForEachinit功能,您会发现有以下内容:init(Range<Int>, content: (Int) -> Content)与您的0 ..< 3的使用相匹配

。在 swift 的许多其他地方,你可以混合使用.....<因为函数要么重载,要么有一个Collection可以使用泛型和RangeExpression协议。在这种情况下,由于除了您的输入之外ForEach没有支持它的Collection,因此重载是唯一合理的选择。

这可以像这样完成:

extension ForEach where Data == ClosedRange<Int>, ID == Int, Content: View {
public init(_ data: ClosedRange<Int>, @ViewBuilder content: @escaping (Int) -> Content) {
self.init(data, id: .self, content: content)
}
}

使用范围运算符实现 ForEach 的解决方案如下:-

对于计数 3 的数组

第一个具有封闭范围的是

ForEach(0...2, id: .self){ index in
Text("(self.array[index])")
}

二是

ForEach(0..<3, id: .self){ index in
Text("(self.array[index])")
}

相关内容

最新更新