被 SwiftUI 中的拖放所困扰

Posted

技术标签:

【中文标题】被 SwiftUI 中的拖放所困扰【英文标题】:Stumped on Drag and Drop in SwiftUI 【发布时间】:2021-07-29 22:12:39 【问题描述】:

我很难尝试让拖放工作,所以也许有人可以看到我哪里出错了。这种工作方式允许我拖动并识别可以和不能放置的位置,但它从不调用 doDrop 函数。另外,我没有看到我在哪里拾取目标。

我的真实应用程序有容器和项目,容器可以接受其他容器或项目 - 基本上是文件和文件夹类型的场景。

import SwiftUI

struct ContentView: View

    @State var stuff = ["ABC", "DEF","GHI","JKL","MNO"]
    @State var isTarget = true
    
    var body: some View
    
        List
        
            ForEach(stuff,id: \.self)
             x in
                Text(x)
                    .onDrag
                         NSItemProvider(object: x as NSString) 
            .onDrop(of: ["public.text"], delegate: doDrop())
        
    
    
    struct doDrop: DropDelegate
    
        func performDrop(info: DropInfo) -> Bool
        
            guard info.hasItemsConforming(to: ["public.text"]) else
            
                return false
            
            if let item = info.itemProviders(for: ["public.text"]).first
            
                item.loadItem(forTypeIdentifier: "public.text", options: nil)
                
                    (data, error) in
                    DispatchQueue.main.async
                    
                        if let data = data as? String
                        
                            print(data)
                        
                    
                
                return true
            
            return false
        
    

【问题讨论】:

不相关,但那种每行一个括号的样式有点难读 imo @aheze 你没看错,代码看起来像 JSON。 【参考方案1】:

您不应为新对象 DoDrop 传递初始值设定项。

传递一个已经初始化的对象,其生命周期不仅限于 onDrop 闭包(例如,您的视图模型或 ContentView 结构本身的自身)。

【讨论】:

不是这样,因为我找到了显示函数被调用的工作示例。我确实发现有人表示 onDrop 在列表中不起作用,需要使用 onInsert,但我也无法做到这一点。我可以成功地从列表拖到列表外的视图,但这不是我想要的。 这很奇怪。我在 App Store 中发布了一个应用程序,它可以拖放到列表中。【参考方案2】:

这应该可以解决报告的问题,尽管我还没有得到它来拾取丢弃的文本。

import SwiftUI

struct ContentView: View, DropDelegate

    @State var stuff = ["ABC", "DEF","GHI","JKL","MNO"]
    @State var isTarget = true

    var body: some View
    
        List
         
            ForEach(stuff,id: \.self)
             x in
                Text(x)
                    .onDrag
                         NSItemProvider(object: x as NSString) 
            .onDrop(of: ["public.text"], delegate: self)
        
    

    func performDrop(info: DropInfo) -> Bool
    
        guard info.hasItemsConforming(to: ["public.text"]) else
        
            return false
        
        if let item = info.itemProviders(for: ["public.text"]).first
        
            item.loadItem(forTypeIdentifier: "public.text", options: nil)
            
                (data, error) in
                DispatchQueue.main.async
                
                    if let data = data as? String
                    
                        print(data)
                    
               
            
            return true
        
        return false
    

顺便说一句,我喜欢把括号放在自己的行上。

【讨论】:

这对我不起作用。它开始拖动,但不会触发 performDrop。 我有同样的问题将 public.text 更改为 public.utf8-plain-text。 这并没有改变任何东西,但我发现您似乎无法拖放到同一个列表中。如果有第二个列表,您可以从第一个拖动到第二个,这样就可以了。

以上是关于被 SwiftUI 中的拖放所困扰的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI onDrag 在设备上运行时不显示预览图像

如何让 swiftui drop 代表被调用

SwiftUI 拖放文件

禁用拖放所选文本

UICollectionView 与 SwiftUI + 拖放重新排序可能吗?

SwiftUI:如何在 macOS 上从 Mail 中拖放电子邮件