How to disambiguate a foreach loop in Xcode with SwiftUI

梦想与她 提交于 2021-02-17 07:08:52

问题


I am trying to create a hexagon grid using swiftUI on Xcode. To loop over the creation of the individual hexagons I am using a foreach loop. However I came Across an error when creating a function that creates a column of hexagons:

private func makeCol(C: Int, Bump:Int) -> some View {
        return ZStack {
            ForEach(-5...5, id: \.self) {Ynumber in                
                self.hexagon(
                    x: (ThreeRooted * self.L * Double(C)) + self.centerWidth,
                    y: (ThreeRooted * self.L * Double(Ynumber)) + self.centerHeight + (ThreeRootedOverTwo * self.L * Bump))
                    .stroke(Color.red, lineWidth: CGFloat(self.L/4.0))
            }
        }
    }

Error: The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions.

To get around this I extracted my location fields in separate variables. However, this gave another error:

private func makeCol(C: Int, Bump:Int) -> some View {
        return ZStack {
            ForEach(-5...5, id: \.self) {Ynumber in
                let xPlot = (ThreeRooted * self.L * Double(C)) + self.centerWidth
                let yPlot = (ThreeRooted * self.L * Double(Ynumber)) + self.centerHeight + (ThreeRootedOverTwo * self.L * Bump)

                self.hexagon(
                    x: xPlot,
                    y: yPlot)
                    .stroke(Color.red, lineWidth: CGFloat(self.L/4.0))
            }
        }
    } 

Error: Unable to infer complex closure return type; add explicit type to disambiguate.

How do I give this loop an explicit type?


回答1:


ForEach is a structure that computes views on demand from an underlying collection of identified data, NOT a loop.

How to create hexagonal grid? Below is one possible approach where I tried to show you how to use ForEach and SwiftUI declarative syntax.

import SwiftUI

struct Hexagon: Shape {
    func path(in rect: CGRect) -> Path {
        Path { (path) in
            path.move(to: .init(x: rect.midX, y: rect.minY))
            path.addLine(to: .init(x: rect.maxX, y: (rect.minY + rect.midY) / 2 ))
            path.addLine(to: .init(x: rect.maxX, y: (rect.maxY + rect.midY) / 2 ))
            path.addLine(to: .init(x: rect.midX, y: rect.maxY))
            path.addLine(to: .init(x: rect.minX, y: (rect.maxY + rect.midY) / 2 ))
            path.addLine(to: .init(x: rect.minX, y: (rect.minY + rect.midY) / 2 ))
            path.closeSubpath()
        }
    }
}

struct ContentView: View {
    var body: some View {
        VStack(spacing: -10) {
            ForEach(0 ..< 3) { j in
                HStack(spacing: 5) {
                    ForEach(0 ..< 4) { i in
                        Hexagon()
                            .fill(Color.yellow)
                            .overlay(
                                Hexagon()
                                .stroke(Color.red, lineWidth: 5)
                            )
                            .frame(width: 50, height: 60)
                    }
                }
                HStack(spacing: 5) {
                    ForEach(0 ..< 3) { i in
                        Hexagon()
                            .stroke(Color.blue, lineWidth: 5)
                            .frame(width: 50, height: 60)
                    }
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

and here is the result

Spacing and frame parameters are fixed here for simplicity, you are better to calculate proper numbers.

init(Range<Int>, content: (Int) -> Content)

Available when Data is Range, ID is Int, and Content conforms to View.

You tried to use

init(Data, id: KeyPath<Data.Element, ID>, content: (Data.Element) -> Content)

Available when Content conforms to View.

and finally we don't have any idea what type returns your hexagon function, it could be Shape, but Shape is protocol, and that could make your trouble. If it is Shape, try define return type as some Shape.

Yes, compiler error reporting is still not very usable with SwiftUI




回答2:


How do I give this loop an explicit type?

ForEach(-5...5, id: \.self) { (Ynumber) -> _ExplicitType_ in
  ...
  return self.hexagon(
            ...
         )
}


来源:https://stackoverflow.com/questions/60230457/how-to-disambiguate-a-foreach-loop-in-xcode-with-swiftui

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!