简体   繁体   English

系统未一致调用 SwiftUI 拖放项提供程序

[英]SwiftUI drag/drop item provider not called consistently by the system

I'm using a DropDelegate to handle drag/drop in SwiftUI on iOS.我正在使用 DropDelegate 在 iOS 上的 SwiftUI 中处理拖放。 I have a simplified sample app here:我在这里有一个简化的示例应用程序:

https://gist.github.com/jhaungs/6ac2c3a34309b7115eef40925c27b1ab https://gist.github.com/jhaungs/6ac2c3a34309b7115eef40925c27b1ab

The problem seems to be an interaction between the SwiftUI framework and my code.问题似乎是 SwiftUI 框架和我的代码之间的交互。 If you attempt to load the itemProvider from DropInfo on the dropEntered or dropUpdated call, the system never calls the loadData function on the model;如果您尝试在dropEntereddropUpdated调用上从DropInfo加载itemProvider ,则系统永远不会调用模型上的loadData函数; but somehow the same code works fine when it's called from performDrop.但不知何故,当从performDrop调用相同的代码时,它可以正常工作

If you set a breakpoint or add a print statement in getItem, you can see that itemProviders is never empty;如果在getItem中设置断点或添加print语句可以看到itemProviders永远不为空; it has exactly one item provider of the correct type (utf8 text).它只有一个正确类型的项目提供者(utf8 文本)。 But calling loadObject on it only invokes loadData, when getItem is called from performDrop.但是当从 performDrop 调用getItem时,对其调用loadObject只会调用loadData So there's some opaque internal state mediating the data transfer.所以有一些不透明的内部状态来调解数据传输。

Any ideas why this is not consistent?任何想法为什么这不一致? It seems like a bug to me.这对我来说似乎是一个错误。

In dropEntered and dropUpdated, I want to know what I'm dragging so I can do stuff like highlight it, or animate it, or perhaps even forbid or cancel the drop, but there's no feedback.dropEntereddropUpdated 中,我想知道我在拖动什么,以便我可以做一些事情,比如突出显示它,或者动画它,或者甚至禁止或取消放置,但没有反馈。

I could be doing this all wrong, too.我也可能做错了这一切。 I've spent quite a bit of time on it, and this is the closest I've gotten it to working.我花了很多时间在它上面,这是我最接近它的工作。 It's not clear that one DropDelegate per item is correct or wise.不清楚每个项目一个 DropDelegate 是否正确或明智。 The documentation is sorely lacking, especially working examples.文档非常缺乏,尤其是工作示例。

There was a suggestion on another StackOverflow question to assign the current item to a viewModel variable in the onDrag, but this creates race conditions where the variable is not consistently set or cleared.有一个关于另一个 StackOverflow 问题的建议,将当前项目分配给 onDrag 中的一个 viewModel 变量,但这会造成竞争条件,即变量未始终设置或清除。

SwiftUI | SwiftUI | Using onDrag and onDrop to reorder Items within one single LazyGrid? 使用 onDrag 和 onDrop 对单个 LazyGrid 中的项目重新排序?

It's a bit unclear to me what you're asking, but if all you need is drag and drop that works in SwiftUI, here's a suggestion based on the same example you linked:我有点不清楚你在问什么,但如果你需要的只是在 SwiftUI 中工作的拖放,这里有一个基于你链接的相同示例的建议:

import SwiftUI
import UniformTypeIdentifiers

struct GridData: Identifiable, Equatable {
    let id: String
}

//MARK: - Model

class Model: ObservableObject {
    @Published var data: [GridData]

    let columns = [
        GridItem(.flexible(minimum: 60, maximum: 60))
    ]

    init() {
        data = Array(repeating: GridData(id: "0"), count: 50)
        for i in 0..<data.count {
            data[i] = GridData(id: String("\(i)"))
        }
    }
}

//MARK: - Grid

struct DemoDragRelocateView: View {
    @StateObject private var model = Model()

    @State private var dragging: GridData? // I can't reset this when user drops view ins ame location as drag started
    @State private var changedView: Bool = false

    var body: some View {
        VStack {
            ScrollView(.vertical) {
               LazyVGrid(columns: model.columns, spacing: 5) {
                    ForEach(model.data) { d in
                        GridItemView(d: d)
                            .opacity(dragging?.id == d.id && changedView ? 0 : 1)
                            .onDrag {
                                self.dragging = d
                                changedView = false
                                return NSItemProvider(object: String(d.id) as NSString)
                            }
                            .onDrop(of: [UTType.text], delegate: DragRelocateDelegate(item: d, listData: $model.data, current: $dragging, changedView: $changedView))
                            
                    }
                }.animation(.default, value: model.data)
            }
        }
        .frame(maxWidth:.infinity, maxHeight: .infinity)
        .background(Color.gray.edgesIgnoringSafeArea(.all))
        .onDrop(of: [UTType.text], delegate: DropOutsideDelegate(current: $dragging, changedView: $changedView))
    }
}

struct DragRelocateDelegate: DropDelegate {
    let item: GridData
    @Binding var listData: [GridData]
    @Binding var current: GridData?
    @Binding var changedView: Bool
    
    func dropEntered(info: DropInfo) {
        
        if current == nil { current = item }
        
        changedView = true
        
        if item != current {
            let from = listData.firstIndex(of: current!)!
            let to = listData.firstIndex(of: item)!
            if listData[to].id != current!.id {
                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 {
        changedView = false
        self.current = nil
        return true
    }
    
}

struct DropOutsideDelegate: DropDelegate {
    @Binding var current: GridData?
    @Binding var changedView: Bool
        
    func dropEntered(info: DropInfo) {
        changedView = true
    }
    func performDrop(info: DropInfo) -> Bool {
        changedView = false
        current = nil
        return true
    }
}

//MARK: - GridItem

struct GridItemView: View {
    var d: GridData

    var body: some View {
        VStack {
            Text(String(d.id))
                .font(.headline)
                .foregroundColor(.white)
        }
        .frame(width: 60, height: 60)
        .background(Circle().fill(Color.green))
    }
}
```

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM