SwiftUI随机颜色棋盘视图无法编译问题求助
问题根源
你这代码的问题出在直接在视图的body里生成随机颜色。SwiftUI的body是会被反复计算的,每次视图刷新时,[Color.green, ...].randomElement()!都会生成新的随机值,这又会触发视图再次刷新,陷入无限循环,最后就导致Xcode编译超时了。
解决办法
提前一次性生成所有棋盘格的随机颜色,存在固定数组里,别让它每次刷新都重新生成。给你两种方案:
方案1:初始化时生成固定颜色(一次性生成,不会变)
struct ChessBoard: View { let rows : Int = 8 let columns : Int = 8 let squareSize: CGFloat @Binding var lastTappedSquareID: Int? // 提前存好所有格子的颜色 private let squareColors: [Color] init(squareSize: CGFloat, lastTappedSquareID: Binding<Int?>) { self.squareSize = squareSize self._lastTappedSquareID = lastTappedSquareID let colorList = [Color.green, Color.blue, Color.brown, Color.darkGray] // 生成64个随机颜色(8x8) self.squareColors = (0..<rows*columns).map { _ in colorList.randomElement()! } } var body: some View { VStack(spacing: 0) { ForEach(0..<rows) { row in HStack(spacing: 0) { ForEach(0..<columns) { column in let id = row * columns + column + 1 let colorIndex = row * columns + column Rectangle() .fill(squareColors[colorIndex]) .frame(width: squareSize, height: squareSize) .id(id) .border(id == lastTappedSquareID ? .red : .clear, width: 3) .onTapGesture { lastTappedSquareID = id } } } } } } }
方案2:用@State存颜色(支持后续重新生成)
如果之后想加个按钮重新生成随机颜色,就用@State来存数组,只有主动修改数组时才会刷新视图:
struct ChessBoard: View { let rows : Int = 8 let columns : Int = 8 let squareSize: CGFloat @Binding var lastTappedSquareID: Int? @State private var squareColors: [Color] = [] private let colorList = [Color.green, Color.blue, Color.brown, Color.darkGray] var body: some View { VStack(spacing: 0) { // 可选:加个按钮重新生成颜色 Button("重新生成颜色") { squareColors = (0..<rows*columns).map { _ in colorList.randomElement()! } } VStack(spacing: 0) { ForEach(0..<rows) { row in HStack(spacing: 0) { ForEach(0..<columns) { column in let id = row * columns + column + 1 let colorIndex = row * columns + column Rectangle() .fill(squareColors[colorIndex]) .frame(width: squareSize, height: squareSize) .id(id) .border(id == lastTappedSquareID ? .red : .clear, width: 3) .onTapGesture { lastTappedSquareID = id } } } } } } .onAppear { // 视图加载时生成初始颜色 squareColors = (0..<rows*columns).map { _ in colorList.randomElement()! } } } }
为啥之前两种颜色的方案能跑?
因为(row + column) % 2 == 0 ? Color.green : Color.blue是固定逻辑,给定row和column,结果是确定的,不会每次刷新都变,所以不会触发无限循环。
内容的提问来源于stack exchange,提问作者Nathanael Tse
相关产品推荐
相关产品推荐

