Swiftui 如何使拖放viewmodifier接受任何对象
我已经创建了一个拖放viewmodifier,它可以按预期工作,但现在我想让它接受任何对象。我可以添加到所有函数、结构和视图修饰符中,但当我尝试将其添加到我的singleton类中时,我得到了“泛型类型中不支持的静态存储属性” 我需要singleton类,这样我就可以将.dropObjectOutside viewmodifier放在视图层次结构中的任何位置,所以我尝试将ID向下转换为字符串,但我似乎无法实现这一点 有没有一种方法可以使这段代码接受任何对象Swiftui 如何使拖放viewmodifier接受任何对象,swiftui,drag-and-drop,downcast,Swiftui,Drag And Drop,Downcast,我已经创建了一个拖放viewmodifier,它可以按预期工作,但现在我想让它接受任何对象。我可以添加到所有函数、结构和视图修饰符中,但当我尝试将其添加到我的singleton类中时,我得到了“泛型类型中不支持的静态存储属性” 我需要singleton类,这样我就可以将.dropObjectOutside viewmodifier放在视图层次结构中的任何位置,所以我尝试将ID向下转换为字符串,但我似乎无法实现这一点 有没有一种方法可以使这段代码接受任何对象 import SwiftUI //
import SwiftUI
// I want this to be any object
struct StopContent: Identifiable {
var id: String = UUID().uuidString
}
// Singleton class to hold drag state
class DragToReorderController: ObservableObject {
// Make it a singleton, so it can be accessed from any view
static let shared = DragToReorderController()
private init() { }
@Published var draggedID: String? // How do I make this a T.ID or downcast T.ID to string everywhere else?
@Published var dragActive:Bool = false
}
// Add ViewModifier to view
extension View {
func dragToReorder(_ item: StopContent, array: Binding<[StopContent]>) -> some View {
self.modifier(DragToReorderObject(sourceItem: item, contentArray: array))
}
func dropOutside() -> some View {
self.onDrop(of: [UTType.text], delegate: DropObjectOutsideDelegate())
}
}
import UniformTypeIdentifiers
// MARK: View Modifier
struct DragToReorderObject: ViewModifier {
let sourceItem: StopContent
@Binding var contentArray: [StopContent]
@ObservedObject private var dragReorder = DragToReorderController.shared
func body(content: Content) -> some View {
content
.onDrag {
dragReorder.draggedID = sourceItem.id
dragReorder.dragActive = false
return NSItemProvider(object: String(sourceItem.id) as NSString)
}
.onDrop(of: [UTType.text], delegate: DropObjectDelegate(sourceItem: sourceItem, listData: $contentArray, draggedItem: $dragReorder.draggedID, dragActive: $dragReorder.dragActive))
.onChange(of: dragReorder.dragActive, perform: { value in
if value == false {
// Drag completed
}
})
.opacity(dragReorder.draggedID == sourceItem.id && dragReorder.dragActive ? 0 : 1)
}
}
// MARK: Drop and reorder
struct DropObjectDelegate: DropDelegate {
let sourceItem: StopContent
@Binding var listData: [StopContent]
@Binding var draggedItem: String?
@Binding var dragActive: Bool
func dropEntered(info: DropInfo) {
if draggedItem == nil { draggedItem = sourceItem.id }
dragActive = true
// Make sure the dragged item has moved and that it still exists
if sourceItem.id != draggedItem {
if let draggedItemValid = draggedItem {
if let from = listData.firstIndex(where: { $0.id == draggedItemValid } ) {
// If that is true, move it to the new location
let to = listData.firstIndex(where: { $0.id == sourceItem.id } )!
if listData[to].id != draggedItem! {
listData.move(fromOffsets: IndexSet(integer: from),
toOffset: to > from ? to + 1 : to)
}
}
}
}
}
func dropUpdated(info: DropInfo) -> DropProposal? {
return DropProposal(operation: .move)
}
func performDrop(info: DropInfo) -> Bool {
dragActive = false
draggedItem = nil
return true
}
}
// MARK: Drop and cancel
struct DropObjectOutsideDelegate: DropDelegate {
// Using a singleton so we can drop anywhere
@ObservedObject private var dragReorder = DragToReorderController.shared
func dropEntered(info: DropInfo) {
dragReorder.dragActive = true
}
func performDrop(info: DropInfo) -> Bool {
dragReorder.dragActive = false
dragReorder.draggedID = nil
return true
}
}
导入快捷界面
//我希望这是任何对象
struct StopContent:可识别{
变量id:String=UUID().UUIString
}
//保持拖动状态的单例类
类DragToReorderController:observeObject{
//将其设置为单例,以便可以从任何视图访问它
静态let shared=DragToReorderController()
私有init(){}
@已发布的var draggedID:String?//如何将其作为T.ID或向下转换的T.ID,以便在其他地方使用String?
@已发布变量dragActive:Bool=false
}
//将ViewModifier添加到视图
扩展视图{
func dragToReorder(uItem:StopContent,array:Binding)->一些视图{
修饰符(DragToReorderObject(sourceItem:item,contentArray:array))
}
func dropOutside()->一些视图{
self.onDrop(属于:[UTType.text],委托:DropObjectOutsideDelegate())
}
}
导入UniformTypeIdentifiers
//标记:视图修改器
结构DragToReorderObject:ViewModifier{
让sourceItem:StopContent
@绑定变量contentArray:[StopContent]
@ObservedObject private var dragReorder=DragToReorderController.shared
func正文(内容:内容)->某些视图{
内容
昂德拉格先生{
dragReorder.draggedID=sourceItem.id
dragReorder.dragActive=false
返回NSItemProvider(对象:字符串(sourceItem.id)作为NSString)
}
.onDrop(of:[UTType.text],委托:DropObjectDelegate(sourceItem:sourceItem,listData:$contentArray,DragEdItem:$DrageOrder.DrageDid,dragActive:$DrageOrder.dragActive))
.onChange(of:dragReorder.dragActive,执行:{中的值
如果值==false{
//拖动完成
}
})
.opacity(dragReorder.draggedID==sourceItem.id&&dragReorder.dragActive?0:1)
}
}
//标记:删除并重新排序
结构DropObjectDelegate:DropDelegate{
让sourceItem:StopContent
@绑定变量listData:[StopContent]
@绑定变量draggedItem:字符串?
@绑定变量dragActive:Bool
func dropEntered(信息:DropInfo){
如果draggedItem==nil{draggedItem=sourceItem.id}
dragActive=true
//确保拖动的项目已移动且仍存在
如果sourceItem.id!=draggedItem{
如果让draggedItemValid=draggedItem{
如果let from=listData.firstIndex(其中:{$0.id==draggedItemValid}){
//如果这是真的,请将其移动到新位置
let to=listData.firstIndex(其中:{$0.id==sourceItem.id})!
如果listData[to].id!=draggedItem{
move(fromOffsets:IndexSet(integer:from),
toOffset:to>from?to+1:to)
}
}
}
}
}
func DropUpdate(信息:DropInfo)->DropProposal{
返回建议(操作:。移动)
}
func performDrop(信息:DropInfo)->Bool{
dragActive=false
draggedItem=零
返回真值
}
}
//马克:放弃并取消
结构DropObjectOutsideDelegate:DropDelegate{
//使用单人床,这样我们可以在任何地方下车
@ObservedObject private var dragReorder=DragToReorderController.shared
func dropEntered(信息:DropInfo){
dragReorder.dragActive=true
}
func performDrop(信息:DropInfo)->Bool{
dragReorder.dragActive=false
dragReorder.draggedID=nil
返回真值
}
}
为此,必须在所有位置添加可识别的通用约束。另外,将Int用于draggedID
而不是String
这是演示代码
// Singleton class to hold drag state
class DragToReorderController: ObservableObject {
// Make it a singleton, so it can be accessed from any view
static let shared = DragToReorderController()
private init() { }
@Published var draggedID: Int?
@Published var dragActive: Bool = false
}
// Add ViewModifier to view
extension View {
func dragToReorder<T: Identifiable>(_ item: T, array: Binding<[T]>) -> some View {
self.modifier(DragToReorderObject(sourceItem: item, contentArray: array))
}
func dropOutside() -> some View {
self.onDrop(of: [UTType.text], delegate: DropObjectOutsideDelegate())
}
}
import UniformTypeIdentifiers
// MARK: View Modifier
struct DragToReorderObject<T: Identifiable>: ViewModifier {
let sourceItem: T
@Binding var contentArray: [T]
@ObservedObject private var dragReorder = DragToReorderController.shared
func body(content: Content) -> some View {
content
.onDrag {
dragReorder.draggedID = sourceItem.id.hashValue
dragReorder.dragActive = false
return NSItemProvider(object: String(sourceItem.id.hashValue) as NSString)
}
.onDrop(of: [UTType.text], delegate: DropObjectDelegate(sourceItem: sourceItem, listData: $contentArray, draggedItem: $dragReorder.draggedID, dragActive: $dragReorder.dragActive))
.onChange(of: dragReorder.dragActive, perform: { value in
if value == false {
// Drag completed
}
})
.opacity((dragReorder.draggedID == sourceItem.id.hashValue) && dragReorder.dragActive ? 0 : 1)
}
}
// MARK: Drop and reorder
struct DropObjectDelegate<T: Identifiable>: DropDelegate {
let sourceItem: T
@Binding var listData: [T]
@Binding var draggedItem: Int?
@Binding var dragActive: Bool
func dropEntered(info: DropInfo) {
if draggedItem == nil { draggedItem = sourceItem.id.hashValue }
dragActive = true
// Make sure the dragged item has moved and that it still exists
if sourceItem.id.hashValue != draggedItem {
if let draggedItemValid = draggedItem {
if let from = listData.firstIndex(where: { $0.id.hashValue == draggedItemValid } ) {
// If that is true, move it to the new location
let to = listData.firstIndex(where: { $0.id == sourceItem.id } )!
if listData[to].id.hashValue != draggedItem! {
listData.move(fromOffsets: IndexSet(integer: from),
toOffset: to > from ? to + 1 : to)
}
}
}
}
}
func dropUpdated(info: DropInfo) -> DropProposal? {
return DropProposal(operation: .move)
}
func performDrop(info: DropInfo) -> Bool {
dragActive = false
draggedItem = nil
return true
}
}
// MARK: Drop and cancel
struct DropObjectOutsideDelegate: DropDelegate {
// Using a singleton so we can drop anywhere
@ObservedObject private var dragReorder = DragToReorderController.shared
func dropEntered(info: DropInfo) {
dragReorder.dragActive = true
}
func performDrop(info: DropInfo) -> Bool {
dragReorder.dragActive = false
dragReorder.draggedID = nil
return true
}
}
//保持拖动状态的单例类
类DragToReorderController:observeObject{
//将其设置为单例,以便可以从任何视图访问它
静态let shared=DragToReorderController()
私有init(){}
@发布变量:Int?
@已发布变量dragActive:Bool=false
}
//将ViewModifier添加到视图
扩展视图{
func dragToReorder(uu项:T,数组:Binding)->一些视图{
修饰符(DragToReorderObject(sourceItem:item,contentArray:array))
}
func dropOutside()->一些视图{
self.onDrop(属于:[UTType.text],委托:DropObjectOutsideDelegate())
}
}
导入UniformTypeIdentifiers
//标记:视图修改器
结构DragToReorderObject:ViewModifier{
让sourceItem:T
@绑定变量contentArray:[T]
@ObservedObject private var dragReorder=DragToReorderController.shared
func正文(内容:内容)->某些视图{
内容
昂德拉格先生{
dragReorder.draggedID=sourceItem.id.hashValue
dragReorder.dragActive=false
返回NSItemProvider(对象:字符串(sourceItem.id.hashValue)作为NSString)
}
.onDrop(of:[UTType.text],委托:DropObjectDelegate(sourceItem:sourceItem,listData:$contentArray,DragEdItem:$DrageOrder.DrageDid,dragActive:$DrageOrder.dragActive))
.onChange(of:dragReorder.dragActive,执行:{中的值
如果值==false{
//拖动完成
}
})
.opacity((dragReorder.draggedID==sourceItem.id.hashValue)&&dragReo