Обновление пути в SwiftUI

#ios #swift #swiftui #core-graphics

#iOS #swift #swiftui #ядро-графика

Вопрос:

У меня есть представление SwiftUI с диаграммой, которая создана с использованием пути и данных из entries массива.

Код:

 struct TodayChartView: View {
    var body: some View {
            GeometryReader { reader in
                    Path { p in
                            for i in 1..<entries.count {
                                p.move(to: CGPoint(x: entries[i-1].x, entries[i-1].y: y))
                                p.addLine(to: CGPoint(entries[i].x: x, entries[i].y: y))
                            }
                        }
                    }.stroke(Color.blue, style: StrokeStyle(lineWidth: 3, lineCap: .round, lineJoin: .round))
                }
}
  

Когда пользователь нажимает кнопку в другом представлении, в entries добавляется новая запись, и я хочу отобразить ее на моем пути. Итак, в принципе, мне нужно как-то вызвать его перерисовку. Есть ли какой-либо способ добиться этого?

Ответ №1:

Передайте entries в качестве параметра в TodayChartView . С entries как @State var в ContentView , TodayChartView перерисовывается при каждом entries изменении.

Вот полный пример (протестирован в Xcode 11.7):

 struct TodayChartView: View {
    let entries: [CGPoint]
    
    var body: some View {
        // GeometryReader { reader in
            Path { p in
                for i in 1..<self.entries.count {
                    p.move(to: CGPoint(x: self.entries[i-1].x, y: self.entries[i-1].y))
                    p.addLine(to: CGPoint(x: self.entries[i].x, y: self.entries[i].y))
                }
            }
            .stroke(Color.blue, style: StrokeStyle(lineWidth: 3, lineCap: .round, lineJoin: .round))
        // }
    }
}

struct ContentView: View {
    @State private var entries: [CGPoint] = [CGPoint(x: 150, y: 150)]
    
    var body: some View {
        VStack(spacing: 20) {
            Button("Add Point") {
                let x = CGFloat.random(in: 0...300)
                let y = CGFloat.random(in: 0...300)
                self.entries.append(CGPoint(x: x, y: y))
            }
            TodayChartView(entries: self.entries)
                .frame(width: 300, height: 300)
        }
    }
}
  

Примечание: Ваш TodayChartView в настоящее время не используется GeometryReader , поэтому я прокомментировал это.

Ответ №2:

Попробуйте этот

     Path { p in
            for i in 1..<entries.count {
                p.move(to: CGPoint(x: entries[i-1].x, entries[i-1].y: y))
                p.addLine(to: CGPoint(entries[i].x: x, entries[i].y: y))
            }
        }
    }.stroke(Color.blue, style: StrokeStyle(lineWidth: 3, lineCap: .round, lineJoin: .round))
    .id(entries)     // << here !!