Бесконечный цикл листа SwiftUI?

#swiftui #ios15

Вопрос:

Это ошибка в SwiftUI? Если вы нажмете «Проверить», он войдет в цикл, бесконечно выкладывая лист за листом. Я не понимаю, почему.

Это происходит на iOS и iPadOS 15

 struct ContentView: View {
    
    @State private var showSheet = false
    @State private var name: String = ""
    @FocusState private var isFocused: Bool
    
    var body: some View {
        VStack {
            Button("Test") { setState() }
        }
        .sheet(isPresented: $showSheet) {
            VStack {
                Text("(showSheet.description), (name)")
                TextField("folder name", text: $name)
                    focused($isFocused)
            }
        }
    }

    private func setState() {
        print("setState")
        showSheet = true
    }
}
 

Ответ №1:

Это опечатка, и обычно ее следует просто закрыть как таковую, но я думаю, что причина достаточно интересна, чтобы оправдать ответ здесь:

 struct ContentView: View {
    
    @State private var showSheet = false
    @State private var name: String = ""
    @FocusState private var isFocused: Bool
    
    var body: some View {
        VStack {
            Button("Test") { setState() }
        }
        .sheet(isPresented: $showSheet) {
            VStack {
                Text("(showSheet.description), (name)")
                TextField("folder name", text: $name)
                    focused($isFocused) //<-- THIS LINE IS MISSING A `.` -- it should be .focused($isFocused)
            }
        }
    }

    private func setState() {
        print("setState")
        showSheet = true
    }
}
 

Поскольку вы пропустили a . в focused строке, focused возвращает модификатор на ContentView себя, а не на TextField . Это означает, что он добавляет копию ContentView в иерархию представлений ниже TextField (поскольку focused возвращает измененную версию self ), а не изменяет TextField на месте.

Это вызывает цикл, но поскольку технически это допустимый код, он не вызывает ошибки компилятора.

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

1. Ha! Спасибо. Я делал то же самое один или два раза раньше — не . включал модификатор и получил очень странный результат, который было трудно отследить. Интересно, можно ли заставить компилятор помочь здесь с предупреждением?

2. Да, это интересный вопрос. Я предполагаю, что это может предупредить вас, если вы возвращаете копию self внутри иерархии, но на самом деле для этого могут быть веские причины (например, в коде модификатора представления, а не только в самом представлении).