Xcode报错:Closure containing control flow statement cannot be used with result builder ‘ViewBuilder’
Xcode报错:Closure containing control flow statement cannot be used with result builder ‘ViewBuilder’

Xcode报错:Closure containing control flow statement cannot be used with result builder ‘ViewBuilder’

展示列表报错

在循环展示列表信息时:

Section("tags") {
    if let friendTag = friend?.tags {
        for tag in friendTag {
            Text(tag)
        }
    }
}

提示报错内容为:

Closure containing control flow statement cannot be used with result builder 'ViewBuilder'

这个错误的原因是 ViewBuilder 不允许在其构造中使用某些控制流语句,例如 for 循环或者 if 语句。如果你需要动态生成视图,应该使用 ForEach 来替代 for 循环。

解决方案

在 Section(“tags”) 中,for 循环是导致错误的地方。要解决这个问题,可以使用 ForEach 来迭代 tags 数组。

Section("tags") {
    if let friendTag = friend?.tags {
        ForEach(friendTag, id:\.self) { tag in
            Text(tag)
        }
    }
}

问题得到解决。

另一种报错场景

在toolbar中尝试使用modelContext获取数据也会这个报错:

.toolbar {
    ToolbarItem(placement: .topBarLeading) {
        do {
            let dices = try modelContext.fetch(FetchDescriptor<Dice>())
        } catch { }
    }
}

报错代码为

Closure containing control flow statement cannot be used with result builder 'ViewBuilder'

报错原因为:在 ToolbarItem 的闭包中使用了控制流语句(如 do-catch)。SwiftUI 的 ViewBuilder 只允许声明视图的语句,而 do-catch 是逻辑控制语句,与 ViewBuilder 的用途不兼容。

解决方法

1、提前处理逻辑

如果需要在 ToolbarItem 中执行逻辑操作(如 fetch 数据),可以将逻辑部分移出到视图构建闭包外,在视图构建前处理逻辑。

var fetchedDices: [Dice] {
    do {
        return try modelContext.fetch(FetchDescriptor<Dice>())
    } catch {
        print("Failed to fetch dices: \(error)")
        return []
    }
}

.toolbar {
    ToolbarItem(placement: .topBarLeading) {
        Text("Dices Count: \(fetchedDices.count)")
    }
}
2、使用异步任务

如果需要在视图加载时异步执行逻辑,可以结合 .task 修饰符。

.toolbar {
    ToolbarItem(placement: .topBarLeading) {
        Text("Dices Count: \(fetchedDices.count)")
    }
}
.task {
    // 异步加载数据
    do {
        fetchedDices = try modelContext.fetch(FetchDescriptor<Dice>())
    } catch {
        print("Failed to fetch dices: \(error)")
    }
}

第三种预览报错场景

如果是在SwiftUI的#Preview{}中出现这一报错:

#Preview {
    @ObservedObject var appStorage = AppStorageManager.shared
    var specialEliminationArea: [(Int, Int)] = []
    for row in 0...2 {  // 报错行
        for col in 2...5 {
            specialEliminationArea.append((row, col))
        }
    }
}

这本质是ViewBuilder不允许直接使用for这种“流程控制”的语法。

#Preview{}里只能放“生成视图的语句”,不能放单纯控制逻辑(比如for、if let、var a = …)

解决方案

把需要控制的逻辑代码,放在 Preview 外面定义成一个临时变量,Preview 里直接用就行。

// 预览外面先写好
let eliminationArea: [(Int, Int)] = (0...2).flatMap { row in
    (2...5).map { col in (row, col) }
}

#Preview {
    @ObservedObject var appStorage = AppStorageManager.shared
    GameGridView(specialEliminationArea:eliminationArea)
}
   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注