I would like to do something like this:
struct HandleUrlDropModifier<Content>: ViewModifier where Content: DynamicViewContent {
@Environment(\.modelContext) var modelContext
var content: Content
func body(content: Content) -> some View {
content
.dropDestination(for: URL.self) { items, index in
// index is Int
handleUrlDrop(items, at: index)
}
}
func handleUrlDrop(_ items: [URL], at index: Int) {
modelContext.insert(...)
}
}
Is that possible somehow?
Writing it as a direct extension doesn't work, since I want to use an @Environtment
variable:
extension DynamicViewContent {
@Environment(\.modelContext) var modelContext // <- not possible
func handleUrlDrop() -> some View {
self
.dropDestination(for: URL.self) { items, index in
modelContext.insert(...)
}
}
}
This works for regular Views, but the .dropDestination
action
is different for a DynamicViewContent
:
struct HandleUrlDropModifier: ViewModifier {
@Environment(\.modelContext) var modelContext
func body(content: Content) -> some View {
content
.dropDestination(for: URL.self) { items, location in
// location is CGPoint
handleUrlDrop(items)
return true
}
}
func handleUrlDrop(_ items: [URL]) {
modelContext.insert(...)
}
}
Instead of a view modifier, write a View
that wraps a DynamicViewContent
and adds the dropDestination
modifier. Then you can wrap this view with a DynamicViewContent
extension, so that it looks like a view modifier.
// this view can conform to DynamicViewContent too!
struct HandleURLDropView<Content: DynamicViewContent>: DynamicViewContent {
@Environment(\.modelContext) var modelContext
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
content.dropDestination(for: URL.self) { items, index in
handleUrlDrop(items)
}
}
func handleUrlDrop(_ items: [URL]) {
// ...
}
// DynamicViewContent conformance
var data: Content.Data { content.data }
}
extension DynamicViewContent {
func handleURLDrop() -> some DynamicViewContent {
HandleURLDropView {
self
}
}
}