You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI macOS应用拖拽功能报错:Cannot find '$article' in scope

错误原因分析
  1. 作用域不匹配:article变量是在List(articles) { article in }的闭包内部定义的,仅在List的循环范围内有效。左侧Text的.onDrop代码处于List外部,完全无法访问到这个article变量,因此会报错找不到$article.title。
  2. 拖拽逻辑设计错误:你试图让DTDropTarget通过绑定接收拖拽内容,但拖拽是跨组件的交互,不能直接绑定列表中动态生成的元素变量。正确的做法是从DropInfo中提取拖拽传递的数据,而非依赖外部绑定。
解决方法

步骤1:重构DTDropTarget,从DropInfo读取拖拽内容

修改DTDropTarget,移除不必要的dragText绑定,直接从DropInfo解析拖拽的文本数据:

struct DTDropTarget: DropDelegate {
    @Binding var dropText: String
    
    func performDrop(info: DropInfo) -> Bool {
        // 从DropInfo中提取文本类型的拖拽数据
        if let itemProvider = info.itemProviders(for: [.text]).first {
            itemProvider.loadObject(ofClass: NSString.self) { (object, error) in
                // 异步操作后切回主线程更新UI
                DispatchQueue.main.async {
                    if let text = object as? String {
                        self.dropText = text
                    }
                }
            }
            return true
        }
        return false
    }
}

步骤2:修正ContentView中的.onDrop调用

移除无效的$article.title参数,直接传递$dropText即可:

struct ContentView: View {
    @State private var dropText = "empty"
    var articles: [MyArticles] = []
    
    var body: some View {
        NavigationView {
            // 左侧拖拽接收区域
            VStack(alignment: .leading) {
                Text(dropText)
                    .padding()
                    .frame(width: 200, height: 100)
                    .border(Color.gray) // 添加边框方便识别拖拽目标范围
                    .onDrop(of: [.text], delegate: DTDropTarget(dropText: $dropText))
            }
            
            // 右侧可拖拽列表
            List(articles) { article in
                NavigationLink(destination: Text(article.title)) {
                    VStack(alignment: .leading) {
                        Text(article.title)
                    }
                    .onDrag {
                        NSItemProvider(object: article.title as NSString)
                    }
                }
            }
        }
        .frame(width: 600, height: 400)
    }
}

步骤3:保留原数据结构

原有的MyArticles和testData无需修改:

struct MyArticles: Identifiable {
    var id = UUID()
    var title: String
}

let testData = [
    MyArticles(title: "Test"),
    MyArticles(title: "Test2")
]
关键说明
  • 拖拽发起端的onDrag将元素title包装成NSItemProvider传递,指定.text类型对应NSString/String。
  • 接收端的performDrop通过info.itemProviders(for: [.text])获取传递的数据,由于loadObject是异步操作,必须切回主线程更新UI。
  • 给接收区域添加边框是为了更直观地识别可拖拽目标,可根据需求自行调整样式。

内容的提问来源于stack exchange,提问作者crimsontides097

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 13:45:47