J'essaie de configurer une vue qui peut afficher plusieurs modaux en fonction du bouton sur lequel vous appuyez.
Lorsque j'ajoute un seul sheet
, tout fonctionne:
.sheet(isPresented: $showingModal1) { ... }
Mais lorsque j'ajoute une autre feuille, seule la dernière fonctionne.
.sheet(isPresented: $showingModal1) { ... }
.sheet(isPresented: $showingModal2) { ... }
METTRE À JOUR
J'ai essayé de faire fonctionner cela, mais je ne sais pas comment déclarer le type de modal
. Je reçois une erreur de Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements
.
struct ContentView: View {
@State var modal: View?
var body: some View {
VStack {
Button(action: {
self.modal = ModalContentView1()
}) {
Text("Show Modal 1")
}
Button(action: {
self.modal = ModalContentView2()
}) {
Text("Show Modal 2")
}
}.sheet(item: self.$modal, content: { modal in
return modal
})
}
}
struct ModalContentView1: View {
var body: some View {
Text("Modal 1")
}
}
struct ModalContentView2: View {
var body: some View {
Text("Modal 2")
}
}
Peut-être que j'ai raté le point, mais vous pouvez y parvenir soit avec un seul appel à .sheet()
, ou plusieurs appels .:
Approche multiple .sheet()
:
import SwiftUI
struct MultipleSheets: View {
@State private var sheet1 = false
@State private var sheet2 = false
@State private var sheet3 = false
var body: some View {
VStack {
Button(action: {
self.sheet1 = true
}, label: { Text("Show Modal #1") })
.sheet(isPresented: $sheet1, content: { Sheet1() })
Button(action: {
self.sheet2 = true
}, label: { Text("Show Modal #2") })
.sheet(isPresented: $sheet2, content: { Sheet2() })
Button(action: {
self.sheet3 = true
}, label: { Text("Show Modal #3") })
.sheet(isPresented: $sheet3, content: { Sheet3() })
}
}
}
struct Sheet1: View {
var body: some View {
Text("This is Sheet #1")
}
}
struct Sheet2: View {
var body: some View {
Text("This is Sheet #2")
}
}
struct Sheet3: View {
var body: some View {
Text("This is Sheet #3")
}
}
approche Single .sheet ():
struct MultipleSheets: View {
@State private var showModal = false
@State private var modalSelection = 1
var body: some View {
VStack {
Button(action: {
self.modalSelection = 1
self.showModal = true
}, label: { Text("Show Modal #1") })
Button(action: {
self.modalSelection = 2
self.showModal = true
}, label: { Text("Show Modal #2") })
Button(action: {
self.modalSelection = 3
self.showModal = true
}, label: { Text("Show Modal #3") })
}
.sheet(isPresented: $showModal, content: {
if self.modalSelection == 1 {
Sheet1()
}
if self.modalSelection == 2 {
Sheet2()
}
if self.modalSelection == 3 {
Sheet3()
}
})
}
}
struct Sheet1: View {
var body: some View {
Text("This is Sheet #1")
}
}
struct Sheet2: View {
var body: some View {
Text("This is Sheet #2")
}
}
struct Sheet3: View {
var body: some View {
Text("This is Sheet #3")
}
}
Cela marche:
.background(EmptyView().sheet(isPresented: $showingModal1) { ... }
.background(EmptyView().sheet(isPresented: $showingModal2) { ... }))
Remarquez comment ils sont imbriqués backgrounds
. Pas deux horizons l'un après l'autre.
Merci à DevAndArtist d'avoir trouvé cela.
Je ne sais pas si cela a toujours été possible, mais dans Xcode 11.3.1 il y a une surcharge de .sheet()
pour exactement ce cas d'utilisation ( https://developer.Apple.com/documentation/swiftui/view/3352792-sheet ). Vous pouvez l'appeler avec un élément identifiable au lieu d'un bool:
struct ModalA: View {
var body: some View {
Text("Hello, World! (A)")
}
}
struct ModalB: View {
var body: some View {
Text("Hello, World! (B)")
}
}
struct MyContentView: View {
enum Sheet: Hashable, Identifiable {
case a
case b
var id: Int {
return self.hashValue
}
}
@State var activeSheet: Sheet? = nil
var body: some View {
VStack(spacing: 42) {
Button(action: {
self.activeSheet = .a
}) {
Text("Hello, World! (A)")
}
Button(action: {
self.activeSheet = .b
}) {
Text("Hello, World! (B)")
}
}
.sheet(item: $activeSheet) { item in
if item == .a {
ModalA()
} else if item == .b {
ModalB()
}
}
}
}
Personnellement, j'imiterais une API NavigationLink. Ensuite, vous pouvez créer une énumération lavable et décider quelle feuille modale vous souhaitez présenter.
extension View {
func sheet<Content, Tag>(
tag: Tag,
selection: Binding<Tag?>,
content: @escaping () -> Content
) -> some View where Content: View, Tag: Hashable {
let binding = Binding(
get: {
selection.wrappedValue == tag
},
set: { isPresented in
if isPresented {
selection.wrappedValue = tag
} else {
selection.wrappedValue = .none
}
}
)
return background(EmptyView().sheet(isPresented: binding, content: content))
}
}
enum ActiveSheet: Hashable {
case first
case second
}
struct First: View {
var body: some View {
Text("frist")
}
}
struct Second: View {
var body: some View {
Text("second")
}
}
struct TestView: View {
@State
private var _activeSheet: ActiveSheet?
var body: some View {
print(_activeSheet as Any)
return VStack
{
Button("first") {
self._activeSheet = .first
}
Button("second") {
self._activeSheet = .second
}
}
.sheet(tag: .first, selection: $_activeSheet) {
First()
}
.sheet(tag: .second, selection: $_activeSheet) {
Second()
}
}
}