I’m engaged on making a customized Popup
View based mostly on a .fullscreenCover
. The .fullscreenCover
is used to put the Popup
content material on display on a semi-transparent background.
Whereas this works on iOS 18, there’s a drawback on iOS 17: When the Popup
content material accommodates a .sheet, the background is just not clear any extra however opaque.
-
- Picture: iOS 17. When exhibiting the Popup an opaque background covers the principle content material. When tapping on the background it turns clear.
-
- Picture: iOS 18. All the things works as meant. When exhibiting the Popup the principle background is roofed with a semi-transparent background.
Eradicating the .sheet(...)
from the Popup content material solves the issue. It doesn’t matter if the sheet is used or not. Including it to the view code is sufficient to set off the issue.
Utilizing a .sheet
inside a .fullscreenCover
shouldn’t be an issue so far as I do know.
Is that this a bug in iOS 17 or is there one thing mistaken with my code?
Code:
struct SwiftUIView: View {
@State var isPresented: Bool = false
@State var sheetPresented: Bool = false
var physique: some View {
ZStack {
VStack {
Colour.pink.body(maxHeight: .infinity)
Colour.inexperienced.body(maxHeight: .infinity)
Colour.yellow.body(maxHeight: .infinity)
Colour.blue.body(maxHeight: .infinity)
}
Button("Present") {
isPresented = true
}
.padding()
.background(.white)
Popup(isPresented: $isPresented) {
VStack {
Button("Dismiss") {
isPresented = false
}
}
.body(maxWidth: 300)
.padding()
.background(
RoundedRectangle(cornerRadius: 20)
.fill(.white)
)
.sheet(isPresented: $sheetPresented) {
Textual content("Hallo")
}
}
}
}
}
struct Popup: View {
@Binding var isPresented: Bool
let content material: () -> Content material
init(isPresented: Binding, @ViewBuilder _ content material: @escaping () -> Content material) {
_isPresented = isPresented
self.content material = content material
}
@State non-public var internalIsPresented: Bool = false
@State non-public var isShowing: Bool = false
let transitionDuration: TimeInterval = 0.5
var physique: some View {
ZStack { }
.fullScreenCover(isPresented: $internalIsPresented) {
VStack {
content material()
}
.body(maxWidth: .infinity, maxHeight: .infinity)
.background(
Colour.black.opacity(0.5)
.opacity(isShowing ? 1 : 0)
.animation(.easeOut(length: transitionDuration), worth: isShowing)
.ignoresSafeArea()
)
.presentationBackground(.clear)
.onAppear {
isShowing = true
}
.onDisappear {
isShowing = false
}
}
.onChange(of: isPresented) { _ in
withoutAnimation {
internalIsPresented = isPresented
}
}
}
}
extension View {
func withoutAnimation(motion: @escaping () -> Void) {
var transaction = Transaction()
transaction.disablesAnimations = true
withTransaction(transaction) {
motion()
}
}
}