我想做这样的事情:
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(...)
}
}
这可能吗?
将其写为直接扩展是行不通的,因为我想使用
@Environtment
变量:
extension DynamicViewContent {
@Environment(\.modelContext) var modelContext // <- not possible
func handleUrlDrop() -> some View {
self
.dropDestination(for: URL.self) { items, index in
modelContext.insert(...)
}
}
}
这适用于常规视图,但
.dropDestination
action
对于 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(...)
}
}
代替视图修饰符,编写一个
View
来包装 DynamicViewContent
并添加 dropDestination
修饰符。然后你可以用 DynamicViewContent
扩展来包装这个视图,这样它看起来就像一个视图修饰符。
// 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
}
}
}