SwiftUI - отображать лист программно

Aug 31 2020

Я хотел бы, чтобы появился модальный лист с несколькими вариантами для выбора пользователем. (Общий лист является прекрасным примером.) Когда пользователь делает выбор, лист параметров исчезает и появляется второй лист с выбранным параметром. В примере с общим листом, если пользователь выбирает печать, общий лист сдвигается вниз, а лист для печати всплывает.

Я могу сделать так, чтобы лист опций появился достаточно легко. Но я не придумал, как получить второй лист. Я попытался прикрепить лист к пустому представлению, а затем использовал UserDefaults, чтобы установить логическое значение, которое активирует второй лист. Ничего.

Первый лист

Button(action: {
   UserDefaults.standard.set(true, forKey: showSelectedOption)
   showOptionForm = true
}) {
   Image(systemName: "square.and.arrow.up")
}
.sheet(isPresented: $showOptionForm) {
   OptionView().environment(\.managedObjectContext, self.moc)
})

Второй лист

EmptyView()
   .sheet(isPresented: $showSelectedOption) {
      SelectedOptionView().environment(\.managedObjectContext, self.moc)
}

Я попытался установить bool, показанный ниже, в .onAppear, но он не вызывается, когда модальный лист отклоняется. Есть ли способ узнать, когда вид больше не закрывается листом? В UIKit это было бы presentationControllerDidDismiss (_ :). Конечно, это предполагает, что моя идея прикрепить второй лист к пустому представлению вообще осуществима.

let showSelectedOption = UserDefaults.standard.bool(forKey: "showSelectedOption")

Ответы

2 Asperi Aug 31 2020 at 22:06

Вот демонстрация возможного подхода - вы активируете второй лист в onDismissпервом. Протестировано с Xcode 12 / iOS 14.

struct DemoTwoSheets: View {
    @State private var firstSheet = false
    @State private var secondSheet = false
    var body: some View {
        VStack {
            Button("Tap") { self.firstSheet = true }
                .sheet(isPresented: $firstSheet, onDismiss: { self.secondSheet = true }) { Text("First sheet") } EmptyView() .sheet(isPresented: $secondSheet) {
                    Text("Second sheet")
                }
        }
    }
}

Обновить:

Вот альтернатива, которая также работает для SwiftUI 1.0. Протестировано с Xcode 11.4 / iOS 13.4 и Xcode 12b5 / iOS 14.

struct DemoTwoSheets: View {
    @State private var firstSheet = false
    @State private var secondSheet = false
    var body: some View {
        VStack {
            Button("Tap") { self.firstSheet = true }
                .sheet(isPresented: $firstSheet, onDismiss: { self.secondSheet = true }) { Text("First sheet") } .background(Color.clear .sheet(isPresented: $secondSheet) {
                        Text("Second sheet")
                    })
        }
    }
}