I am trying to replace a standard sheet modifier with a custom one that applies the same changes to the content of all sheets as to the main view (it can be useful for changing accent color, although there is a UIKit approach for it, but specifically I want to apply privacySensitive modifier to all sheets).
The code that creates the modifiers compiles ok:
import SwiftUI
struct SheetForItem<T, C>: ViewModifier where T: Identifiable, C: View {
var item: Binding<T?>
var onDismiss: (() -> Void)? = nil
var sheetContent: (T) -> C
func body(content: Content) -> some View {
content.sheet(item: item, onDismiss: onDismiss) {
sheetContent($0).privacySensitive()
}
}
}
extension View {
func appSheet<T, Content>(
item: Binding<T?>,
onDismiss: (() -> Void)? = nil,
content: @escaping (T) -> Content
) -> some View where T: Identifiable, Content: View {
modifier(SheetForItem(item: item, onDismiss: onDismiss, sheetContent: content))
}
}
Mostly it works, but some of the usages of appSheet
in the chain of other modifiers instead of sheet
do not compile with an error:
Type () cannot conform to View.
The example below doesn't compile (but it will compile if I replace appSheet
with sheet
):
import SwiftUI
enum Actions:Identifiable {
case action1
case action2
var id: Self { self }
}
struct AppSheetExample: View {
@State var showActions = false
@State private var action: Actions?
var body: some View {
Button { showActions = true } label: {
Image(systemName: "square.and.pencil")
.resizable()
.scaledToFit()
.frame(width: 24, height: 24)
}
.confirmationDialog("Actions", isPresented: $showActions, titleVisibility: .visible) {
Button("Action 1") { action = .action2 }
Button("Action 2") { action = .action2 }
}
.appSheet(item: $action) { sheet in
switch sheet {
case .action1: Text("Action 1")
case .action2: Text("Action 2")
}
}
}
}
Thank you!
You need to mark your content closure with
@ViewBuilder
since you're not explicitly returning aView
(i.e:return Text("Action 1")
):