#swiftui
#swiftui
Вопрос:
Я пытаюсь отобразить предупреждение после закрытия листа. Но когда я обновляю @Binding на листе, предупреждение на домашней странице не появилось. Я не знаю, в чем проблема сейчас. Кто-нибудь может мне объяснить? Это проблема использования @Binding? Если метод / логика выполнения этого неверны, какой метод мне следует использовать?
struct ContentView: View {
@State private var showSheet = false
@State var showAlert = false
var body: some View {
VStack {
Text("sheet")
.onTapGesture(perform: {
self.showSheet.toggle()
})
}
.sheet(isPresented: $showSheet) {
AddView(showAlert: self.$showAlert, showSheet: self.$showSheet)
}
.alert(isPresented: $showAlert){
Alert(title: Text("Important message"), message: Text("Wear sunscreen"), dismissButton: .default(Text("Got it!")))
}
}
}
struct AddView: View {
@Binding var showAlert: Bool
@Binding var showSheet: Bool
var body: some View {
Button("Dismiss") {
self.showSheet = false
self.showAlert = true
}
}
}
Ответ №1:
Лист имеет другой контекст, поэтому оповещение, настроенное как в исходном коде, там не отображается.
Вот измененный код, который работает. Протестировано с Xcode 12.1 / iOS 14.1
struct ContentView: View {
@State private var showSheet = false
@State var showAlert = false
var body: some View {
VStack {
Text("sheet")
.onTapGesture(perform: {
self.showSheet.toggle()
})
}
.sheet(isPresented: $showSheet, onDismiss: { self.showAlert = true }) {
AddView(showSheet: self.$showSheet)
}
.alert(isPresented: $showAlert){
Alert(title: Text("Important message"), message: Text("Wear sunscreen"), dismissButton: .default(Text("Got it!")))
}
}
}
struct AddView: View {
@Binding var showSheet: Bool
var body: some View {
Button("Dismiss") {
self.showSheet = false
}
}
}
Комментарии:
1. Спасибо за ваш комментарий. Как, если я хочу изменить значение showAlert на листе? Что-то вроде триггера чем угодно, но не только отклонить?
2. Как я уже писал, у листа другой контекст иерархии представлений, и вы не можете показывать прикрепленное предупреждение вне иерархии представлений листов, как в вашем исходном сообщении. Вы можете легко проверить это — вместо того, чтобы закрыть лист на кнопке, просто попробуйте показать предупреждение… Итак, если вам нужно отобразить предупреждение на листе, вам нужно использовать другой модификатор предупреждения в addView.
Ответ №2:
Реальная проблема заключается в том, что вы пытаетесь одновременно закрыть лист и отобразить предупреждение. В вашем коде, если вы добавите задержку на 0,5 секунды к предупреждению, оно будет работать:
struct AddView: View {
@Binding var showAlert: Bool
@Binding var showSheet: Bool
var body: some View {
Button("Dismiss") {
self.showSheet = false
DispatchQueue.main.asyncAfter(deadline: .now() 0.5) {
self.showAlert = true
}
}
}
}
Тем не менее, гораздо проще написать это так:
struct ContentView: View {
@State private var showSheet = false
@State var showAlert = false
var body: some View {
VStack {
Button(action: {
self.showSheet.toggle()
}, label: {
Text("sheet")
})
.accentColor(.primary)
}
.sheet(isPresented: $showSheet, onDismiss: showAlertFunction, content: {
AddView()
})
.alert(isPresented: $showAlert){
Alert(title: Text("Important message"), message: Text("Wear sunscreen"), dismissButton: .default(Text("Got it!")))
}
}
func showAlertFunction() {
showAlert.toggle()
}
}
struct AddView: View {
@Environment(.presentationMode) var presentationMode
var body: some View {
Button("Dismiss") {
self.presentationMode.wrappedValue.dismiss()
}
}
}
Комментарии:
1. Спасибо за ваш комментарий. Могу ли я узнать, почему это должно быть отложено? Не могли бы вы немного объяснить? Спасибо.
2. Я не знаю технического ответа. Это часто случается в SwiftUI, когда вы пытаетесь одновременно отображать 2 вещи (оповещения, таблицы действий, листы, полноэкранные обложки и т. Д.). Похоже, что Xcode путается, какой вид отображается на экране. Я полагаю, что здесь вы пытались отобразить предупреждение на первом экране, в то время как пользователь находится на втором экране, и поскольку Xcode знает, что вы находитесь на втором экране, он не будет отображать предупреждение на фоновом экране. Задерживая на 0,5 секунды, вы даете время для закрытия второго экрана, поэтому, когда вы пытаетесь отобразить предупреждение, оно уже отображается на экране переднего плана.