swiftui почему нельзя назначить optional?

#swift #swiftui

#swift #swiftui

Вопрос:

Почему нельзя назначить необязательный параметр?

Индекс был выделен, но значение по-прежнему не отображается

Помогите мне, спасибо!

 struct TestView: View {
    @State private var index: Int? = nil
    @State private var show: Bool = false
    
    var body: some View {
        VStack {
            Text("Hello, world!")
                .onTapGesture {
                    self.index = 1
                    self.show = true
                    print(self.index as Any)
                }
        }
        .fullScreenCover(isPresented: $show) {
            if let index = self.index {
                Text("value:(index)")
            } else {
                Text("not value")
            }
        }
    }
}
  

Версия Xcode 12.0 beta 2

Комментарии:

1. if self.index != nil не делайте этого, узнайте об условном выжидании, if let index = self.index { ... }

2. @Alexander-Переустановите Monica, но можете ли вы сделать это при закрытии в представлении SwiftUI?

3. @Alexander-Переустановите monica спасибо, я пытался развернуть, но индекс не значение, запутался!

4. @JoakimDanielson Хорошая мысль, я помню, что по этому поводу были проблемы. Разве они не решили это, хотя?

5. @Alexander-Переустановите Monica, По крайней мере, не в Xcode 11, я еще не тестировал Xcode 12 / SwiftUI 2.0.

Ответ №1:

SwiftUI полагается на @State переменную, заставляющую body средство получения пересчитываться при его изменении. Чтобы это сработало, body средство получения должно зависеть определенным образом от @State переменной. Проблема в вашем коде в том, что это не так.

Чтобы убедиться в этом, мы можем сократить ваш код до более простого примера:

 struct ContentView: View {
    @State var message = "Hey"
    @State var show: Bool = false
    var body: some View {
        VStack {
            Button("Test") {
                message = "Ho"
                show = true
            }
        }
        .sheet(isPresented: $show) {Text(message)}
    }
}
  

Мы меняем message на Ho, но когда отображается таблица, на ней по-прежнему написано Hey. Это потому, что ничего не произошло для body пересчета. Вы могли бы сказать: А как насчет фразы Text(message) ? Да, но это в закрытии; он уже был вычислен и message уже был захвачен.

Чтобы убедиться в правильности того, что я говорю, просто добавьте текст, отображаемый message непосредственно в главном интерфейсе:

 struct ContentView: View {
    @State var message = "Hey"
    @State var show: Bool = false
    var body: some View {
        VStack {
            Button("Test") {
                message = "Ho"
                show = true
            }
            Text(message)
        }
        .sheet(isPresented: $show) {Text(message)}
    }
}
  

Теперь ваш код работает! Конечно, мы также отображаем нежелательный текст в интерфейсе, но суть в том, что простого Text(message) , не в замыкании, достаточно, чтобы весь body получатель был пересчитан при message изменениях. Итак, мы правильно объяснили явление, о котором вы спрашиваете.

Итак, каково реальное решение? Как мы можем заставить content замыкание работать так, как мы ожидаем, без добавления дополнительного текста в интерфейс? Один из способов такой:

 struct ContentView: View {
    @State var message = "Hey"
    @State var show: Bool = false
    var body: some View {
        VStack {
            Button("Test") {
                message = "Ho"
                show = true
            }
        }
        .sheet(isPresented: $show) {[message] in Text(message)}
    }
}
  

Включив message в список захвата для нашего закрытия, мы заставляем body средство получения зависеть от message переменной, и теперь код ведет себя так, как требуется.

Комментарии:

1. Отлично!, Отлично!, Спасибо!