我回顾了关于SwiftUI拖放重新排序的堆栈溢出的一些问题,这个问题特别有用:SwiftUI | Using onDrag and onDrop to reorder Items within one single LazyGrid?
我希望扩展这个功能,在我的SwifUI应用程序中,我从一个项目列表拖到另一个项目列表中。假设我有一个Task列表:
//TaskView.swift
ScrollView{
VStack{
ForEach(model.tasks, id: \.self){ task in
Text(task.name)
.onDrag{
NSItemProvider(object: String(task.id) as NSString)
}
}
}
}...and还有一个Project列表,可以将Task拖到上面以将其移动到该项目:
//ProjectView.swift
ScrollView{
VStack{
ForEach(model.projects, id: \.self){ project in
Text(project.name)
.onDrop(of: [UTType.text], delegate: ProjectDropDelegate(project: project))
}
}
}我挣扎的部分是在我的ProjectDropDelegate,在那里我试图确定几件事:
id是什么,这样我就可以对它采取行动了?(或者,理想情况下,我可以使用整个Task对象)我不知道如何使我的NSItemProvider在.onDrag中使用字符串以外的任何东西,并且仍然使用我的SwiftUI拖放功能。值得注意的是,我的Task和Project对象是核心数据类。
如何使NSItemProvider包含键值对,以便传递一个类型标识符字符串,如myapp.task (用于上面的#1 )和id (用于#2)?
发布于 2021-03-11 21:56:55
经过进一步的调查,我找到了一个更简单的方法来处理这一切。我认为NSItemProvider有点像鲱鱼,如果你只需要将数据从应用程序的一个部分移到另一个部分就行了。我是这样做的,看起来效果很好。
当我生成任务列表时,我提到了model.tasks。下面是关于它的更多信息:
class TaskModel: ObservableObject {
static let shared = TaskModel()
@Published var tasks = [Task]()
var draggedTask: Task? //<-- I added this
//...
}我在我的模型中添加了一个draggedTask选项,然后在我的onDrag修饰符中设置它,如下所示:
Text(task.name)
.onDrag{
model.draggedTask = task
NSItemProvider(object: NSString())
}我只是将一个空的String对象传递给NSItemProvider,以满足它拖拽某样东西的要求。然后,在我的ProjectDropDelegate中,我可以拥有我需要的所有东西,包括设置一个悬停的UI状态:
import SwiftUI
import UniformTypeIdentifiers
struct ProjectDropDelegate: DropDelegate {
@Binding var hovered: Bool
var project: Project?
var modelTask = TaskModel.shared
//MARK: Check before we start
func validateDrop(info: DropInfo) -> Bool {
//Allow the drop to begin with any String set as the NSItemProvider
return info.hasItemsConforming(to: [UTType.text])
}
//MARK: Drop UI State
func dropEntered(info: DropInfo) {
//Show the hovered state if we have a draggedTask
hovered = modelTask.draggedTask != nil
}
func dropExited(info: DropInfo) {
hovered = false
}
//MARK: Drop and Save
func performDrop(info: DropInfo) -> Bool {
if let task = modelTask.draggedTask{
//Save my task using modelTask...
return true
}else{
return false
}
}
}这比我最初做的要简单得多。
发布于 2022-01-14 13:24:05
遇到了同样的问题。像这样的东西会有用的:
NSItemProvider(item: letter as NSString, typeIdentifier: "public.plain-text")这样做是行不通的:
NSItemProvider(item: letter as NSString, typeIdentifier: "com.myapp.mytype")Bug还是特性?特性!
第二个自定义类型标识符不能工作的原因是该UTI尚未在任何地方声明(尚未)。
解决方案是将您的自定义类型声明为UTI:
打开项目>目标>信息>导出类型Identifiers
com.myapp.mytype public.data现在,这将起作用(您可以提交任何支持NSSecureCoding的对象):
NSItemProvider(item: letter as NSString, typeIdentifier: "com.myapp.mytype")构建并运行您的应用程序,重新排序您的列表现在将工作!
https://stackoverflow.com/questions/66589447
复制相似问题