如何使得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 文件内容。

相关推荐
Java小白笔记3 小时前
Mac中安装homebrew
macos
HerayChen6 小时前
HbuildderX运行到手机或模拟器的Android App基座识别不到设备 mac
android·macos·智能手机
hairenjing11236 小时前
在 Android 手机上从SD 卡恢复数据的 6 个有效应用程序
android·人工智能·windows·macos·智能手机
半桶水专家7 小时前
go语言中package详解
开发语言·golang·xcode
小李飞刀李寻欢9 小时前
Mac电脑如何解压rar压缩包
macos·rar·解压
Java小白笔记9 小时前
Mac中禁用系统更新
macos
AndyFrank9 小时前
mac crontab 不能使用问题简记
linux·运维·macos
Mac新人9 小时前
一招解决Mac没有剪切板历史记录的问题
macos·mac
王拴柱9 小时前
Mac保护电池健康,延长电池使用寿命的好方法
macos·mac
daa209 小时前
macos中安装和设置ninja
macos