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

visionOS应用能否实现跨窗口拖放?附SwiftUI代码示例

visionOS双窗口拖放功能实现方案

完全可以在visionOS的两个窗口之间实现拖放功能,SwiftUI提供的拖放API原生支持跨窗口交互,以下是具体实现步骤和代码示例:

1. 定义可传输的数据类型

先定义遵循Transferable协议的数据模型(也可直接使用系统支持的文本、图片等类型),用于跨窗口传递数据:

import SwiftUI
import UniformTypeIdentifiers

struct TransferItem: Transferable, Identifiable {
    let id = UUID()
    let content: String
    
    // 定义纯文本格式的传输规则
    static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(exportedContentType: .plainText) { item in
            Data(item.content.utf8)
        } importing: { data in
            guard let content = String(data: data, encoding: .utf8) else {
                throw NSError(domain: "TransferError", code: 0, userInfo: [NSLocalizedDescriptionKey: "无法解析拖放数据"])
            }
            return TransferItem(content: content)
        }
    }
}

2. 在ContentView中实现拖放UI

修改你的ContentView,添加可拖动元素和可接收拖放的区域:

struct ContentView: View {
    @EnvironmentObject var sharedState: SharedState
    @State private var localItems: [TransferItem] = [
        TransferItem(content: "测试内容1"),
        TransferItem(content: "测试内容2")
    ]
    
    var body: some View {
        VStack(spacing: 20) {
            Text("当前窗口")
                .font(.title)
            
            // 可拖动的列表项
            List(localItems) { item in
                Text(item.content)
                    .padding(8)
                    .background(Color.blue.opacity(0.1))
                    .cornerRadius(6)
                    .onDrag {
                        return .init(item: item)
                    }
            }
            .frame(height: 150)
            
            // 可接收拖放的区域
            RoundedRectangle(cornerRadius: 12)
                .fill(Color.gray.opacity(0.2))
                .frame(height: 120)
                .overlay(
                    Text("拖放到这里")
                        .font(.headline)
                        .foregroundColor(.gray)
                )
                .onDrop(of: [.plainText], delegate: DropReceiver(items: $localItems))
        }
        .padding()
    }
}

// 自定义拖放接收代理
class DropReceiver: DropDelegate {
    @Binding var items: [TransferItem]
    
    init(items: Binding<[TransferItem]>) {
        self._items = items
    }
    
    // 处理拖放完成事件
    func performDrop(info: DropInfo) -> Bool {
        guard let provider = info.itemProviders(for: [.plainText]).first else {
            return false
        }
        
        provider.loadTransferable(type: TransferItem.self) { [weak self] result in
            DispatchQueue.main.async {
                switch result {
                case .success(let item):
                    if let item = item {
                        self?.items.append(item)
                    }
                case .failure(let error):
                    print("拖放失败: \(error.localizedDescription)")
                }
            }
        }
        return true
    }
    
    // 可选:拖入/拖出时的视觉反馈
    func dropEntered(info: DropInfo) {
        // 比如修改区域背景色
    }
    
    func dropExited(info: DropInfo) {
        // 恢复区域背景色
    }
}

关键说明

  • 跨窗口拖放是visionOS系统原生支持的能力,无需额外配置窗口权限,只要两个窗口的视图都正确实现拖放逻辑即可。
  • 若需要同步两个窗口的数据状态,可结合你已有的SharedState,在拖放完成后更新共享对象,实现数据联动。
  • 除纯文本外,还可扩展支持图片、自定义文件类型等,只需修改TransferRepresentation的内容类型即可。

内容的提问来源于stack exchange,提问作者János

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 06:35:27