#swift #swiftui
#swift #swiftui
Вопрос:
У меня есть переменная состояния в представлении @State private var value: Int
SwiftUI. Когда я использую это состояние в логических операторах, например, so value == 10
, оно не обновляется, если передается во второе представление.
Например, выделение в следующем никогда не меняется:
struct TestView: View {
@State private var value = 5
var body: some View {
Button("update value") {
withAnimation { value = value 5 }
}
Text("(value)").padding()
MyTestView(highlighted: value == 5).padding()
MyTestView(highlighted: value == 10).padding()
MyTestView(highlighted: value == 15).padding()
}
}
struct MyTestView: View {
@State var highlighted: Bool = false
var body: some View {
Text("test")
.background(highlighted ? Color.red : Color.white)
}
}
Комментарии:
1. ваше второе редактирование вопроса отличается от ночи и дня! какой точный вопрос вы задали!
Ответ №1:
Из документации разработчика Apple:
SwiftUI управляет хранением любого свойства, которое вы объявляете как состояние. При изменении значения состояния представление аннулирует его внешний вид и пересчитывает тело. Используйте состояние как единственный источник истины для данного представления.
Итак, когда ваше значение, обернутое в состояние, изменяется, тело будет пересчитано. В приведенном выше примере вы не показываете ничего, что могло бы изменить ваше значение состояния. При создании вашего представления в первый раз компилятор проверит первое значение вашей переменной «value», а затем соответствующим образом установит ваш текст. Чтобы внести изменения в этот текст, вам необходимо изменить переменную состояния.
Button(action: {
//Here you update your State variable, which will force the body to recalculate
self.value = 15
})
{
Text("Update variable")
}
Редактировать:
Поскольку вы опубликовали свой код, вот решение. Вам не нужно объявлять highlighted
, как State
в вашем MyTestView
. Просто объявите его как var
, и он будет работать. Как говорит Apple, объявите свои значения состояния закрытыми, чтобы не изменять их извне. Здесь, в вашем примере, состояние неверно, потому что вы не изменяете это значение изнутри своего тела.
struct MyTestView: View {
var highlighted: Bool = false
var body: some View {
Text("test")
.background(highlighted ? Color.red : Color.white)
}
}
Отредактируйте, чтобы отобразить решение с использованием привязки
Существует решение с использованием привязки, однако это изменит вашу логику и на самом деле не является необходимым в ваших вариантах использования, как обсуждалось в комментарии:
struct ContentView: View {
@State private var value = 5
var body: some View {
Button("update value") {
withAnimation { value = value 5 }
}
Text("(value)").padding()
MyTestView(highlighted: $value, border: 5).padding()
MyTestView(highlighted: $value, border: 10).padding()
MyTestView(highlighted: $value, border: 15).padding()
}
}
struct MyTestView: View {
@Binding var highlighted: Int
var border : Int
var body: some View {
Text("test")
.background(highlighted == border ? Color.red : Color.white)
}
}
Даст вам тот же эффект, однако не очень хорошо
Комментарии:
1. @davidev, привязка была бы правильным ответом, а не тем, что вы ответили здесь! это неправильный ответ! Я НЕ знаю, как ваш ответ может быть правильным ответом!
2. @Omid Я не знаю, зачем вам использовать привязку в этом случае. Вы не меняете значение в MyTestView. Из документации Apple: «Используйте привязку для создания двустороннего соединения между свойством, в котором хранятся данные, и представлением, которое отображает и изменяет данные». Если вы хотите изменить значение внутри MyTestView и хотите обновить свой родительский вид, вы бы использовали привязку. Как кнопка переключения, которая отправляет обновления состояния своему родителю
3. @davidev, посмотрите код, который он использует для рендеринга представления, значение == 5, значение == 10, значение == 15! Ваше объяснение привязки не является полным объяснением, загляните на веб-сайт Apple для получения дополнительной информации, если бы он просто вызывал MyTestView вовремя, и после этого не нужно было бы обновлять это представление, я мог бы понять ваш ответ, но, как вы видите, он начинает изменять значение, выделенное в testView! ЭТО ОЗНАЧАЕТ, что MyTestView также должен обновиться! ваше понимание привязки неверно, «для создания двустороннего соединения», которое является частью задания привязки не всех
4. @Omid Я действительно ценю ваши усилия и готов мне помочь! Спасибо большое. Но я должен признать, что показанный мной код — всего лишь пример, демонстрирующий проблему, с которой я столкнулся. На самом деле это действительно так, что вложенное представление не имеет никакого контроля над тем, выделено оно или нет. Вот почему я использовал состояние, а не привязку. Так что в моем конкретном случае я все еще думаю, что это правильный ответ.
5. Также на этой платформе вам лучше принимать быстрые решения. Буквально через час я заметил, что мой первоначальный пример был плохим, и придумал улучшенный. Я получил достаточно запросов на дизлайки и закрытие, чтобы поторопиться, пока он не закрылся ^^