如何使得Macos的剪切板感知fileURL并当fileURL被执行paste 动作时 回调到某个监听的函数 从而来填充file content

问题及尝试:

我在做一个跨平台文件拷贝的功能,文件可能是从其他操作系统比如Linux 或者Windows 拷贝到Macos上, 但是我试过所有可以hook NSPasteboard的方法,确实没有找到可以监听macos 剪切板的方法,因为fileURL 确实在NSPasteboard是一个类型的数据,这个数据的value 其实是一个路径,我们可以通过下载macos 里面的一个工具 Pasteboard Viewer: ‎Pasteboard Viewer on the App Store

从工具中我们可以看到当我自macos 本地copy一个file时 会有fileURL的数据类型被加到NSPasteboard里面 从截图可以得知 fileURL数据类型的值其实就是一个路径,因此我们通过NSPasteboard 提供的回调方法

@protocol NSPasteboardItemDataProvider <NSObject>

/* Implemented by the data provider of a pasteboard item, to provide the data for a particular UTI type.

*/

@required

  • (void )pasteboard:(nullable NSPasteboard *)pasteboard item:(NSPasteboardItem *)item provideDataForType:(NSPasteboardType)type NS_SWIFT_NONISOLATED;

无法在paste的时候才触发到这个方法 但是其他的数据类型比如 plain text/HTML/Bitmap 都是可以自回调的时候触发到这里,这时你就可以在回调的这个函数里去fetch 具体的内容 可能这些内容来自其他平台,但是fileURL不行, 我尝试过,现象是一旦加到NSPasteboard里, 这个方法就会被触发,我也想了一下原因,可能是因为fileURL的数据类型的值就是一个文件路径, 所以也决定了这个数据大小不会很大,不像HTML 或者是Bitmap 可大可小,这个文件路径的长度是可以预估的,还有一个原因可能是因为如果fileURL被加入到了NSPasteboard里但是不提供给其具体的路径,当用户在Finder 或者其他应用(支持文件拷贝)里进行粘贴时,用户是无法进行paste的因为paste选项不会被高亮。

探究Microsoft Remote Desktop:

这也是一个支持文件拷贝的跨系统的app,当我运行mac版本的app 从windows里往mac拷贝文件时, 通过Pasteboard Viewer,我们可以看到RDP创建里一个临时的Placeholder文件, 如下:
当我在RDP里面的windows copy一个aa.txt时候,RDP会在macos上创建一个Placeholder文件,从而监听这个Placeholder文件 当用户粘贴时, 空壳子文件才会fetch 远端windows的内容到Placeholder文件,当Placeholder文件内容fetch 完毕时,macos 的paste动作起作用, 我可以听到macos的操作声 文件被paste到了用户指定的位置。在查看了RDP的流程后 ,给了我一些灵感,发现从监听NSPasteboard 切换到了监听创建的PlaceHolder 文件,那问题又来了 怎么监听这个placeholder文件呢?

寻找Macos提供的API:

为了监听创建的PlaceHolder文件,我们需要寻找文件监听API,当时有两个思路一个是因为FileURL也属于NSURL的一种,所以查看NSURL的监听API自然是一个路子,还有一个思路是因为placeholder文件也属于文件,所以自然也会去看filesystem相关的API, 事实证明第一条路子不通,第二条路有效, 因此我找到了两个Macos提供的API,NSFilePresenter 和 NSFilecoordinator,里面提供了read 回调方法 relinquishPresentedItemToReader: | Apple Developer Documentation

所以方法就是当文件在远端系统拷贝时,触发消息发送到本地,本地创建Placeholder,并在创建完placeholder 后 将这个fileURL注册成一个NSFilePresenter 并将创建的filepresenter 实例加入到NSFileCoordinator上,这样当用户执行paste 操作时 NSPasteboard会访问这个PlaceHolder 并回调到relinquishPresentedItemToReader, 在这里不执行Read()方法NSPasteboard就不会被释放就会一直等待 直到在这个方法里执行read, 所以这样就block了NSPasteboard去粘贴文件 与此同时可以从远端fetch 文件内容。

相关推荐
黑科技iOS上架11 小时前
iOS framework/dylib动态库定向加固实战
macos·ios·objective-c·cocoa·审核·ios混淆·执行程序差异化
神奇的小猴程序员1 天前
苹果Mac电脑玩我的世界没有版本?用PCL-R即可!
macos
灵韵aura1 天前
macOS 的指令缩写
macos
yqj2343 天前
ESP32-S3中小智项目优化内容
ide·macos·xcode
程序鉴定师3 天前
2026年深圳小程序/App开发公司技术选型指南:从架构设计到交付标准全维度评估
java·小程序·uni-app·php·objective-c
Mininglamp_27183 天前
Cider量化配置与性能调优:在M系列Mac上压榨Mano-P的每一点推理性能
macos
xuefuhe3 天前
MacOS EAGAIN无法打开terminal
macos
传奇开心果编程4 天前
【SwiftUI入门练中学】第7课 动画与手势:让界面更灵动
学习·macos·ui·ios·swiftui·swift
the3clipse4 天前
MacOS、Linux 与 Windows 视频编解码对比:AV1、HEVC、ProRes 与硬件加速优劣势
linux·windows·macos·hevc·av1·视频解码·硬件解码
传奇开心果编程5 天前
【SwiftUI娓娓道来】第3课:让界面活起来——交互与动画指南
学习·macos·ui·ios·swiftui·swift