3

How do I redraw Shape with new data when this data is new "source of truth"? The following shows, that only "Text("...") view gets updated with the ObservedObject. The Shape draws itself only once.

import SwiftUI

struct ContentView: View {
    @ObservedObject var cntrl:Controller=Controller()
    var body: some View {
        VStack {
            subviewone(cntrl: cntrl)
            graph(cntrl: cntrl)
                .stroke()
                .fill(Color.red)
            subviewone(cntrl: cntrl)
        }.padding(.all)
    }
}

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

struct graph: Shape {
    @ObservedObject var cntrl:Controller
    func path(in rect: CGRect) -> Path {
        print("function beeing called")
        return Path { path in
            path.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: CGFloat(100-cntrl.test), startAngle: Angle.init(degrees: 0), endAngle: Angle.init(degrees: 360), clockwise: true)
        }
    }


}

struct subviewone: View {
    @ObservedObject var cntrl:Controller
    var body: some View {
        VStack {
            Text("******")
            Text("\(cntrl.test)")
            Text("******")

        }

    }
}

class Controller:ObservableObject {

    @Published var test=0

    init() {
        _ = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) {_ in
            self.test+=1
        }
    }

}

The code works if i omit .stroke() and .fill(Color.red)


struct ContentView: View {
    @ObservedObject var cntrl:Controller=Controller()
    var body: some View {
        VStack {
            subviewone(cntrl: cntrl)
            graph(cntrl: cntrl)
            subviewone(cntrl: cntrl)
        }.padding(.all)
    }
}

Thank you for any suggestions. Libor

matyasl
  • 295
  • 2
  • 11

2 Answers2

0

try this - tested with 13.4

struct ContentView: View {

    @EnvironmentObject var controller : Controller

    var body: some View {
        VStack {
            subviewone()
                .environmentObject(controller)
            graph(radius: controller.test)
                .stroke()
                .fill(Color.red)
            subviewone()
            .environmentObject(controller)
        }.padding(.all)
    }
}

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

struct graph: Shape {

    @State var radius : CGFloat

    func path(in rect: CGRect) -> Path {
        print("function beeing called")
        return Path { path in
            path.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: CGFloat(100-radius), startAngle: Angle.init(degrees: 0), endAngle: Angle.init(degrees: 360), clockwise: true)
        }
    }


}

struct subviewone: View {
    @EnvironmentObject var controller : Controller
    var body: some View {
        VStack {
            Text("******")
            Text("\(controller.test)")
            Text("******")

        }

    }
}

class Controller:ObservableObject {

    @Published var test : CGFloat = 0

    init() {
        _ = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) {_ in
            self.test+=1
        }
    }

}
Chris
  • 7,579
  • 3
  • 18
  • 38
  • Thank you Chris again. I had to change the first "@EnvironmentObject var controller : Controller" to "@ObservedObject var controller=Controller()" and then it worked. Do you understand why my version does not work? When I delete the .stroke() and .fill(Color.red), the Shape object starts being redrawn as expected and code works. Only that I get filled circle, not just the border. – matyasl Apr 02 '20 at 13:29
0

On Shape, you can never call stroke and fill in one go, because the first calling stroke or fill return a View, no long a Shape.

Juguang
  • 621
  • 2
  • 5
  • 15