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

相关推荐
他们都不看好你,偏偏你最不争气2 小时前
【iOS】 单例模式
macos·objective-c·cocoa
FreeBuf_9 小时前
苹果用户速更新!macOS存严重漏洞,用户隐私数据面临泄露风险
macos
Thomas21439 小时前
macos deepctr_torch虚拟环境配置
macos
wxl7812279 小时前
MacOS 运行CosyVoice
macos·cosyvoice·语音自然
lichong95110 小时前
【混合开发】vue+Android、iPhone、鸿蒙、win、macOS、Linux之video 的各种状态和生命周期调用说明
android·vue.js·macos
程序务虚论10 小时前
mac M1上安装windows虚拟机报错
windows·macos·parallels
今天头发还在吗13 小时前
【Go】:mac 环境下GoFrame安装开发工具 gf-cli——gf_darwin_arm64
macos·golang·go·gf-cli
小妖66616 小时前
MAC在home下新建文件夹报错“mkdir: test: Operation not supported”
macos
北冥有鱼被烹20 小时前
【问题解决】mac笔记本遇到鼠标无法点击键盘可响应处理办法?(Command+Option+P+R)
macos
开开心心loky20 小时前
[iOS] push 和 present Controller 的区别
ui·ios·objective-c·cocoa