SwiftUI поощряет декларативный подход - вам не нужно (и на самом деле нельзя) получить доступ к любому представлению напрямую, чтобы сохранить ссылку на него. Вашим представлениям могут быть предоставлены данные, и всякий раз, когда эти данные изменятся, они будут обновляться.
В этом случае вы можете иметь DisplayingRect
для сохранения свойства цвета, а затем иметь жест касания для каждого Rectangle
найдите правильную структуру в вашем массиве rects
по идентификатору и измените свойство цвета.
Чтобы отделить logi c от вашего представления и сделать его более тестируемым, вы можете захотеть создать некоторый класс модели представления, который охватывает это, но помещая все это в ваше представление, будет работать без этих преимуществ.
Этот подход может выглядеть примерно так (тестирование локально и работает):
struct DisplayingRect: Identifiable {
let id = UUID()
var color = Color.red
var width: CGFloat
var height: CGFloat
var xAxis: CGFloat
var yAxis: CGFloat
init(
width: CGFloat,
height: CGFloat,
xAxis: CGFloat = 0,
yAxis: CGFloat = 0)
{
self.width = width
self.height = height
self.xAxis = xAxis
self.yAxis = yAxis
}
}
final class ContentViewModel: ObservableObject {
@Published
private(set) var rects: [DisplayingRect] = [
.init(width: 100, height: 100),
.init(width: 100, height: 100),
.init(width: 100, height: 100)
]
func didTapRectangle(id: UUID) {
guard let rectangleIndex = rects.firstIndex(where: { $0.id == id }) else {
return
}
rects[rectangleIndex].color = .blue
}
}
struct ContentView: View {
@ObservedObject
var viewModel = ContentViewModel()
var body: some View {
VStack {
ForEach(viewModel.rects) { rect in
Rectangle()
.fill(rect.color)
.frame(width: rect.width, height: rect.height)
.offset(x: rect.xAxis, y: rect.yAxis)
.onTapGesture {
self.viewModel.didTapRectangle(id: rect.id)
}
}
}
}
}
В этом случае оболочка свойства @ObservedObject
вместе с протоколом ObservableObject
позволяют представлению обновляться при каждом изменении данных, которые оно использует из viewModel
. Чтобы автоматически сигнализировать о свойствах, которые должны вызывать обновление представления sh, используется оболочка свойства @Published
.
https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-observedobject-to-manage-state-from-external-objects