微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决系统未一致调用SwiftUI拖放项提供程序

我正在使用DropDelegate处理iOS上SwiftUI中的拖放。我在这里一个简化的示例应用程序:

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

问题似乎是SwiftUI框架和我的代码间的交互 。如果您尝试在 dropEntered dropUpdated 调用中从 DropInfo 加载 itemProvider ,则系统永远不会调用 loadData 函数;但是从 performDrop

调用代码时,以某种方式可以正常工作

如果您在 getItem 中设置了断点或添加了打印语句,则可以看到 itemProviders 永远不会为空;它只有一个正确类型的项目提供者(utf8文本)。但是,当从performDrop调用 getItem 时,对其调用 loadobject 只会调用 loadData 。因此,存在一些不透明的内部状态来介导数据传输。

有什么想法为什么这不一致?对我来说似乎是个虫子。

dropEntered dropUpdated 中,我想知道我要拖动的内容,因此我可以进行诸如突出显示,设置动画或什至禁止或取消之类的操作下降,但没有反馈。

我也可能做错了。我花了很多时间,这是我最接近它工作的时间。尚不清楚每个项目一个DropDelegate是正确还是明智的。非常缺少该文档,尤其是工作示例。

关于另一个StackOverflow问题,有人建议将当前项目分配给onDrag中的viewmodel变量,但这会创建竞态条件,在该条件下不会始终设置或清除该变量。

SwiftUI | Using onDrag and onDrop to reorder Items within one single LazyGrid?

解决方法

我有点不清楚您在问什么,但如果您只需要在 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))
    }
}
```

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。