How it works
PresentationContentInteraction is a set of constants that tells SwiftUI how to resolve a gesture conflict inside a resizable presentation. When a sheet has multiple detents and its content scrolls, a swipe is ambiguous: it could either resize the sheet or scroll the content. This type lets you declare which behavior wins, so you reach for it whenever a scrollable sheet feels like it's fighting the user's drag. You apply one of its values through the presentationContentInteraction(_:) modifier rather than constructing it directly.
Give the sheet resizable detents first
The interaction setting only matters when the presentation can change size, so it presumes a set of
presentationDetents. In the example the sheet declares[.medium, .large], which is exactly the situation where a drag is ambiguous between resizing to.largeand scrolling the content.Apply the policy with presentationContentInteraction(_:)
Attach
presentationContentInteraction(_:)to the content inside the sheet's closure, passing the constant you want. Here.presentationContentInteraction(.scrolls)sits alongside.presentationDetents(...)so the rule travels with this specific presentation.Prefer scrolling with .scrolls
The
.scrollsvalue makes a swipe move the scrollable content first; the sheet only resizes once scrolling can't continue (for example, when the content is already at the top and the user keeps dragging down). TheScrollViewof rows in the example responds to drags immediately rather than snapping the sheet to a new detent.Prefer resizing with .resizes
The
.resizesvalue is the inverse: a swipe changes the sheet's detent first and only scrolls the content once the largest detent is reached. This is the default-feeling behavior, and it's the constant you swap in when the sheet itself, not its content, should own the gesture.Treat it as a value, not a constructed object
PresentationContentInteractionhas no initializer you call yourself; you choose among the static members.scrollsand.resizesand hand the result to the modifier. Because it's a plain value type, the policy is fixed for the lifetime of the presentation it's attached to.
.presentationContentInteraction(.scrolls) to .presentationContentInteraction(.resizes) and drag up on the rows: instead of scrolling, the sheet now expands from .medium to .large before the content moves.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct PresentationContentInteractionDemo: View {
@State private var showing = true
var body: some View {
Color.clear
.sheet(isPresented: $showing) {
ScrollView {
VStack(spacing: 12) {
ForEach(0..<20) { i in
Text("Row \(i)")
.frame(maxWidth: .infinity)
.padding()
.background(.quaternary)
}
}
.padding()
}
.presentationDetents([.medium, .large])
.presentationContentInteraction(.scrolls)
}
.padding()
}
}