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

在SwiftUI macOS中实现多本地文件URL的复制粘贴与拖放

实现macOS SwiftUI应用的文件拖放与粘贴功能(筛选.raw文件)

核心实现思路

在SwiftUI视图中同时支持Finder文件拖入和复制文件粘贴,提取文件绝对URL后筛选出后缀为.raw的文件,最终存入URL数组。


完整代码示例

import SwiftUI
import AppKit

struct RawFileImporterView: View {
    // 存储筛选后的.raw文件URL数组
    @State private var rawFileURLs: [URL] = []
    
    var body: some View {
        VStack(spacing: 20) {
            Text("拖入或粘贴.raw文件到这里")
                .font(.title)
                .foregroundColor(.secondary)
            
            // 展示已导入的文件列表
            List(rawFileURLs, id: \.self) { url in
                Text(url.lastPathComponent)
            }
        }
        .frame(minWidth: 400, minHeight: 300)
        // 绑定拖放代理,处理Finder文件拖入
        .onDrop(of: [.fileURL], delegate: RawFileDropDelegate(rawFileURLs: $rawFileURLs))
        // 监听系统粘贴命令,处理粘贴操作
        .onCommand(#selector(NSPasteboard.paste(_:))) {
            handlePaste()
        }
    }
    
    // 处理粘贴逻辑
    private func handlePaste() {
        let pasteboard = NSPasteboard.general
        guard let items = pasteboard.pasteboardItems else { return }
        
        var newURLs: [URL] = []
        for item in items {
            // 从粘贴板提取文件URL
            if let urlStr = item.string(forType: .fileURL), let fileURL = URL(string: urlStr) {
                // 筛选.raw后缀文件(不区分大小写)
                if fileURL.pathExtension.lowercased() == "raw" {
                    newURLs.append(fileURL)
                }
            }
        }
        
        // 去重后更新数组,避免重复导入同一文件
        let existingPaths = Set(rawFileURLs.map { $0.path })
        let uniqueURLs = newURLs.filter { !existingPaths.contains($0.path) }
        rawFileURLs.append(contentsOf: uniqueURLs)
    }
}

// 自定义拖放代理类,处理文件拖入逻辑
class RawFileDropDelegate: DropDelegate {
    @Binding var rawFileURLs: [URL]
    
    init(rawFileURLs: Binding<[URL]>) {
        self._rawFileURLs = rawFileURLs
    }
    
    func performDrop(info: DropInfo) -> Bool {
        let itemProviders = info.itemProviders(for: [.fileURL])
        
        for provider in itemProviders {
            provider.loadObject(ofClass: URL.self) { [weak self] url, error in
                guard let self = self, let fileURL = url as? URL, error == nil else { return }
                
                // 筛选.raw后缀文件
                if fileURL.pathExtension.lowercased() == "raw" {
                    DispatchQueue.main.async {
                        // 去重后添加到数组
                        if !self.rawFileURLs.contains(fileURL) {
                            self.rawFileURLs.append(fileURL)
                        }
                    }
                }
            }
        }
        return true
    }
    
    // 可选:拖入时的视图高亮逻辑
    func dropEntered(info: DropInfo) {
        // 可在此修改视图样式,比如背景色
    }
    
    func dropExited(info: DropInfo) {
        // 恢复视图原始样式
    }
}

// 预览视图
struct RawFileImporterView_Previews: PreviewProvider {
    static var previews: some View {
        RawFileImporterView()
    }
}

关键代码解析

  1. 拖放功能:

    • 使用.onDrop(of:delegate:)修饰符,指定接受fileURL类型的数据
    • 自定义DropDelegate代理,在performDrop方法中提取拖入的URL,筛选.raw文件后更新数组
    • 用DispatchQueue.main.async确保UI更新在主线程执行
  2. 粘贴功能:

    • 通过.onCommand(#selector(NSPasteboard.paste(_:)))监听系统粘贴命令
    • 从NSPasteboard.general提取粘贴的文件URL,同样筛选.raw后缀
    • 用Set存储已导入文件路径,实现高效去重
  3. 细节处理:

    • pathExtension.lowercased()确保不区分大小写(.RAW也能被识别)
    • 去重逻辑避免重复添加同一文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 02:58:12