SwiftUI macOS应用拖拽功能报错:Cannot find '$article' in scope
错误原因分析
- 作用域不匹配:
article变量是在List(articles) { article in }的闭包内部定义的,仅在List的循环范围内有效。左侧Text的.onDrop代码处于List外部,完全无法访问到这个article变量,因此会报错找不到$article.title。 - 拖拽逻辑设计错误:你试图让
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
相关产品推荐
相关产品推荐

