Buried in the iOS 14.5 beta 3 release notes is this little update:
You can now apply multiple
sheet(isPresented:onDismiss:content:)
andfullScreenCover(item:onDismiss:content:)
modifiers in the same view hierarchy. (74246633)
What does this mean in practice? As a comparison, here’s a simple View
and its accompanying model.
In this iOS 14.4 example:
- there’s only one
.sheet
modifier - the modifier has a switch statement on an
enum
of potential sheets to display - the model has an additional property of
displaySheet
to control when sheets are displayed
struct ContentView: View {
@StateObject private var model = ContentViewModel()
var body: some View {
VStack(spacing: 10) {
Button(action: {
model.sheetToDisplay = .green
}, label: {
Text("Show Sheet 0")
})
Button(action: {
model.sheetToDisplay = .red
}, label: {
Text("Show Sheet 1")
})
Button(action: {
model.sheetToDisplay = .blue
}, label: {
Text("Show Sheet 2")
})
}
.sheet(isPresented: $model.displaySheet, content: { //1
switch model.sheetToDisplay { // 2
case .green:
Color.green
case .red:
Color.red
case .blue:
Color.blue
case .none:
EmptyView()
}
})
}
}
class ContentViewModel: ObservableObject {
enum SheetToDisplay {
case green, red, blue, none
}
@Published var displaySheet: Bool = false // 3
@Published var sheetToDisplay: SheetToDisplay = .none {
didSet {
sheetToDisplay != .none ? (displaySheet = true) : (displaySheet = false)
}
}
}
Now, however, things have been simplified. In this updated version for iOS 14.5:
- There are multiple
.sheet
modifiers - Each sheet has its own isPresented property in the model
struct ContentView: View {
@StateObject private var model = ContentViewModel()
var body: some View {
VStack(spacing: 10) {
Button(action: {
model.showGreen = true
}, label: {
Text("Show Green")
})
Button(action: {
model.showRed = true
}, label: {
Text("Show Red")
})
Button(action: {
model.showBlue = true
}, label: {
Text("Show Blue")
})
}
.sheet(isPresented: $model.showGreen, content: { // 1
Color.green
})
.sheet(isPresented: $model.showRed, content: { // 1
Color.red
})
.sheet(isPresented: $model.showBlue, content: { // 1
Color.blue
})
}
}
class ContentViewModel: ObservableObject {
@Published var showGreen: Bool = false // 2
@Published var showRed: Bool = false // 2
@Published var showBlue: Bool = false // 2
}
With multiple sheets being permitted, and each sheet having its own isPresented binding in the model, I find the code to be that little bit more logical.1
-
If you try the updated code on <= iOS 14.4, only the blue sheet will display. ↩︎