SwiftUI модальная презентация работает только один раз от navigationBarItems - PullRequest
2 голосов
/ 02 марта 2020

Вот ошибка в SwiftUI, когда вы показываете модальное от кнопки внутри элементов панели навигации. В приведенном ниже коде кнопка 1 работает должным образом, но кнопка 2 работает только один раз:

struct DetailView: View {

    @Binding var isPresented: Bool
    @Environment (\.presentationMode) var presentationMode

    var body: some View {
        NavigationView {
            Text("OK")
            .navigationBarTitle("Details")
            .navigationBarItems(trailing: Button(action: {
                self.isPresented = false
                // or:
                // self.presentationMode.wrappedValue.dismiss()
            }) {
                Text("Done").bold()
            })
        }
    }
}

struct ContentView: View {

    @State var showSheetView = false

    var body: some View {
        NavigationView {
            Group {
                Text("Master")
                Button(action: { self.showSheetView.toggle() }) {
                    Text("Button 1")
                }
            }
            .navigationBarTitle("Main")
            .navigationBarItems(trailing: Button(action: {
                self.showSheetView.toggle()
            }) {
                Text("Button 2").bold()
            })
        }.sheet(isPresented: $showSheetView) {
            DetailView(isPresented: self.$showSheetView)
        }
    }
}

Эта ошибка с середины прошлого года, и она все еще в Xcode 11.3.1 + iOS 13.3 Simulator и iOS 13.3.1 iPhone XS.

Есть ли какой-нибудь обходной путь, чтобы заставить кнопку работать?

РЕДАКТИРОВАТЬ:

  1. Кажется, что область нажатия идет где-то внизу, и можно нажать кнопку ниже, чтобы показать модальный режим.

Временное решение этой проблемы - использовать режим встроенной панели навигации: .navigationBarTitle("Main", displayMode: .inline)

1 Ответ

2 голосов
/ 02 марта 2020

Что ж, проблема в неправильном расположении (кажется, нарушены ограничения) кнопки панели навигации после закрытия листа

Это хорошо видно в отладке иерархии представлений:

demo

Вот исправление (обходной путь, конечно, но безопасный, потому что даже после исправления проблемы он продолжит работать). Идея состоит не в том, чтобы бороться со сломанной версткой, а просто в создании еще одной кнопки, поэтому движок верстки сам удаляет старые плохие кнопки и добавляет новую, обновляющую разметку. Инструмент для этого достаточно известен - используйте .id()

demo2

Итак, модифицированный код:

struct ContentView: View {

    @State var showSheetView = false
    @State private var navigationButtonID = UUID()

    var body: some View {
        NavigationView {
            Group {
                Text("Master")
                Button(action: { self.showSheetView.toggle() }) {
                    Text("Button 1")
                }
            }
            .navigationBarTitle("Main")
            .navigationBarItems(trailing: Button(action: {
                self.showSheetView.toggle()
            }) {
                Text("Button 2").bold() // recommend .padding(.vertical) here
            }
            .id(self.navigationButtonID)) // force new instance creation
        }
        .sheet(isPresented: $showSheetView) {
            DetailView(isPresented: self.$showSheetView)
                .onDisappear {
                    // update button id after sheet got closed
                    self.navigationButtonID = UUID()
                }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...