Не делай area
@State
;просто сделайте его вычисляемой переменной:
@State var height: CGFloat = 50.0
@State var width: CGFloat = 100.0
var area: CGFloat {
width * height
}
var body: some View {
VStack {
Text("Width: \(width)")
Text("Height: \(height)")
Text("Area \(area)")
Button(action: {
self.height *= 2
}) {
Text("Double height")
}
Button(action: {
self.width += 10
}) {
Text("Add 10 to width")
}
}
}
Я добавил некоторый код, чтобы проиллюстрировать, что если width
или height
изменится, area
тоже изменится, потому что width
или height
причина измененияпредставление должно быть перерисовано, так как они @State
. Поскольку area
вычисляется, при перерисовке представления определяется, что area
является произведением обновленных значений width
и height
. Однако выполнение этой функции, как вы сказали в текущем решении, также должно работать.
Если вы хотите, чтобы area
было @State
, чтобы вы могли передать его другим представлениям как Binding
,сделайте это:
struct ContentView: View {
@State var height: CGFloat = 50.0
@State var width: CGFloat = 100.0
var area: Binding<CGFloat> {
Binding(get: {
self.height * self.width
}) { (newVal) in
}
}
var body: some View {
VStack {
Text("Width: \(width)")
Text("Height: \(height)")
Text("Area \(area.wrappedValue)")
BindingView(num: area)
BindingView(num: $height)
Button(action: {
self.height *= 2
}) {
Text("Double height")
}
Button(action: {
self.width += 10
}) {
Text("Add 10 to width")
}
}
}
struct BindingView: View {
@Binding var num: CGFloat
var body: some View {
Text("Binding number: \(num)")
}
}
Я создал BindingView
в качестве примера того, как использовать привязки по-разному. Для переменных @State
вы фактически превращаете их в Binding
, добавляя префикс $
, но поскольку область явно Binding
, вам не нужен $
. Также для доступа к значению внутри Binding
, вы просто делаете переменную .wrappedValue
.