создать область переменной @State, основанную на двух значениях ширины @State и высоте var @State - PullRequest
1 голос
/ 15 октября 2019

Как вы комбинируете несколько переменных состояния, чтобы сформировать другую?

Я хочу изменить значение высоты ИЛИ ширины при некотором взаимодействии с пользователем, и чтобы все в представлении обновлялось соответствующим образом. Таким образом, высота ИЛИ ширина изменится, и область изменится.

Я думаю, это выглядело бы примерно так

@State var width: CGFloat = 50.0
@State var height: CGFloat = 100.0


@State var area: CGFloat // somehow equal to width*height

текущее решение просто вызывает func

func area() -> CGFloat {
  width * height
}

1 Ответ

3 голосов
/ 15 октября 2019

Не делай 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.

...