I have a TextField that dictates the angle of a solar panel, the default is 10 degrees.
If I alter this to 80 the variables update as shown below:
What doesn't happen is that the Path drawing the panels doesn't get refreshed. The text clearly does.
displayPanelSpacing is called which in turn calls drawPanels. From the print statement in drawPanels I know that it is receiving the correct, updated numbers.
The grey lines only seem to be generating when the view loads for the first time. What am I doing wrong?
struct displayPanelSpacing: View{
@ObservedObject var variables: Variables
@State private var changeLine = false
@State private var offset: CGFloat = 20.0
var body: some View {
VStack {
Text("Panel Spacing " + String(variables.tiltAngle) + "°")
drawPanels(variables: variables)
.stroke(changeLine ? Color(.red) : .gray, lineWidth: 3.0)
.frame(width: (GlobalVariables.screenWidth - 64), height: 150)
.padding(.leading, 16)
.padding(.trailing, 16)
.scaleEffect(changeLine ? 0.5 : 1.0)
.overlay(DrawSun(radius: 25).foregroundColor(.orange))
// .animation(Animation.linear(duration: 1.0), value: offset)
}
}
}
struct drawPanels: Shape {
@ObservedObject var variables: Variables
func path(in rect: CGRect) -> Path {
let result = variables.ed()
let edEndX = result.endX
let edEndY = result.endY
let baselineY = rect.maxY - 0
let baselineXOffset = 10
let panelY = Int(rect.maxY) - edEndY
let panel1X = baselineXOffset + edEndX
let panel2X = baselineXOffset + Int(rect.midX) + edEndX
var path = Path()
path.move(to: CGPoint(x: rect.minX + 10, y: baselineY))
path.addLine(to: CGPoint(x: panel1X, y: panelY))
path.move(to: CGPoint(x: rect.midX + 10, y: baselineY))
path.addLine(to: CGPoint(x: panel2X, y: panelY))
let _ = print("Received", String(edEndY), String(panelY))
return path
}
}
The input TextField is:
struct PanelSpacingView: View {
@StateObject var variables: Variables = Variables()
...
var body: some View {
...
HStack {
Text("Tilt Angle")
.padding(.leading, 16)
TextField("Tilt Angle", value: $variables.tiltAngle, formatter: formatter)
.textFieldStyle(.roundedBorder)
.disableAutocorrection(true)
.padding(.leading, 16)
.padding(.trailing, 16)
Text("°")
.padding(.trailing, 16)
}
Although the Shape
protocol includes View
it seems it does not
work with the @ObservedObject var variables: Variables
in the DrawPanels
.
So I suggest you use a simpler approach, using a @Binding
in DrawPanels
as shown in the example code.
Without a complete workable code, all I can do, is propose an approach that should work. Adjust the code to your specific needs.
struct DisplayPanelSpacing: View {
@ObservedObject var variables: Variables
@State private var changeLine = false
@State private var offset: CGFloat = 20.0
var body: some View {
VStack {
Text("Panel Spacing " + String(variables.tiltAngle) + "°")
DrawPanels(angle: $variables.tiltAngle) // <-- here, pass whatever is needed
.stroke(changeLine ? .red : .gray, lineWidth: 3.0)
.frame(width: (GlobalVariables.screenWidth - 64), height: 150)
.padding(.leading, 16)
.padding(.trailing, 16)
.scaleEffect(changeLine ? 0.5 : 1.0)
.overlay(DrawSun(radius: 25).foregroundColor(.orange))
.animation(Animation.linear(duration: 1.0), value: offset)
}
}
}
struct DrawPanels: Shape {
@Binding var angle: Int // <-- here
func path(in rect: CGRect) -> Path {
let result = Result(endX: angle, endY: 33) // <-- here, whatever the equivalent of `variables.ed()`
let edEndX = result.endX
let edEndY = result.endY
let baselineY = rect.maxY - 0
let baselineXOffset = 10
let panelY = Int(rect.maxY) - edEndY
let panel1X = baselineXOffset + edEndX
let panel2X = baselineXOffset + Int(rect.midX) + edEndX
var path = Path()
path.move(to: CGPoint(x: rect.minX + 10, y: baselineY))
path.addLine(to: CGPoint(x: panel1X, y: panelY))
path.move(to: CGPoint(x: rect.midX + 10, y: baselineY))
path.addLine(to: CGPoint(x: panel2X, y: panelY))
return path
}
}
// for testing
struct ContentView: View {
@StateObject var variables: Variables = Variables()
var body: some View {
VStack {
HStack {
Text("Tilt Angle").padding(.leading, 16)
TextField("Tilt Angle", value: $variables.tiltAngle, formatter: NumberFormatter())
.textFieldStyle(.roundedBorder)
.disableAutocorrection(true)
.padding(.leading, 16)
.padding(.trailing, 16)
Text("°").padding(.trailing, 16)
}
DisplayPanelSpacing(variables: variables)
}
}
}
// for testing
class Variables: ObservableObject {
@Published var tiltAngle = 10
}
// for testing
struct Result {
var endX: Int
var endY: Int
}