【问题标题】:SwiftUI ForEach with index - "The compiler is unable to type-check this expression in reasonable time"带有索引的 SwiftUI ForEach -“编译器无法在合理的时间内对该表达式进行类型检查”
【发布时间】:2021-10-20 14:11:40
【问题描述】:

在我正在编写的 swiftUI 视图中,我需要使用 ForEach,访问列表的每个元素它的索引。我能找到的大部分信息都说使用.enumerated(),如ForEach(Array(values.enumerated()), id: \.offset) { index, value in }

但是,当我尝试这样做时,我认为:

/// A popover displaing a list of items.
struct ListPopover: View {
    // MARK: Properties
    /// The array of vales to display.
    var values: [String]
    
    /// Whether there are more values than the limit and they are concatenated.
    var valuesConcatenated: Bool = false
    
    /// A closure that is called when the button next to a row is pressed.
    var action: ((_ index: Int) -> Void)?
    /// The SF symbol on the button in each row.
    var actionSymbolName: String?
    
    // MARK: Initializers
    init(values: [String], limit: Int = 10) {
        if values.count > limit {
            self.values = values.suffix(limit - 1) + ["\(values.count - (limit - 1)) more..."]
            valuesConcatenated = true

        } else {
            self.values = values
        }
    }
    
    // MARK: Body
    var body: some View {
        VStack {
            ForEach(Array(values.enumerated()), id: \.offset) { index, value in
                HStack {
                    if !(index == values.indices.last && valuesConcatenated) {
                        Text("\(index).")
                            .foregroundColor(.secondary)
                    }

                    Text(value)
                    
                    Spacer()

                    if action != nil && !(index == values.indices.last && valuesConcatenated) {
                        Spacer()

                        Button {
                            action!(index)
                        } label: {
                            Image(systemName: actionSymbolName ?? "questionmark")
                        }
                        .frame(alignment: .trailing)
                    }
                }
                .if((values.count - index) % 2 == 0) { view in
                    view.background(
                        Color(.systemGray5)
                            .cornerRadius(5)
                    )
                }
            }
        }
    }
}

我在var body: some View { 线上收到错误The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

我还注意到这段代码会导致一些其他问题,比如让 Xcode 自动完成变得非常慢。

有什么想法可以解决这个问题吗?这似乎是一个非常简单的视图,我认为我正在做我应该做的ForEach

谢谢!

【问题讨论】:

  • 在 12.5 或 13.0b4 上无法重现。过去,我注意到 Xcode 有时在 SwiftUI 中使用 && 进行布尔评估时会出现问题,因此我会考虑为那些可以拆分的函数构建辅助函数。
  • 不要不要使用id作为\.offset - 改用\.element。当元素发生变化时,使用偏移会导致问题。

标签: swift swiftui swiftui-foreach swift-compiler


【解决方案1】:

这是一个非常具有误导性的错误。它真正的意思是你在body 中搞砸了一些东西,但是编译器无法找出错误,所以它把它扔给body 本身。找到它的最简单方法是在匹配的大括号中注释掉 body 的部分内容,直到错误消失。在您的情况下,问题在于:

            .if((values.count - index) % 2 == 0) { view in
                view.background(
                    Color(.systemGray5)
                        .cornerRadius(5)
                )
            }

我不确定您要做什么,但 .if 不是有效的语法,我不确定 view 是什么或它应该来自哪里。

【讨论】:

  • 我敢打赌,OP 正在使用类似这样的东西 (stackoverflow.com/a/57685253/560942),这是 SwiftUI 中的常见扩展
  • 是的,.if 是正确的,我应该在我的帖子中提到。我已经尝试注释掉它的不同部分,我可以编译代码,但是即使我删除了除ForEach 之外的所有内容,Xcode 仍然非常慢。
  • 这就是您创建Minimal, Reproducible Example 的原因。我对 ForEach 没有任何问题。现在我添加了该扩展,它正在为我构建。因此,我会尝试备用:清理构建文件夹,并删除您的 DerivedData 文件夹。
  • 12.5.1 我认为?无论最新的非测试版是什么。
  • 您清理了构建文件夹并删除了项目的 DerivedData 吗?
猜你喜欢
  • 2021-10-26
  • 1970-01-01
  • 2020-06-30
  • 2020-02-14
  • 1970-01-01
  • 1970-01-01
  • 2019-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多