swift - 使用 NSEvent 拖动文件时出错。(苹果系统)
问题描述
我想将文件拖到我的窗口,然后执行操作。
我尝试使用此答案中提供的以下片段来区分您是在拖动文件还是窗口。
// In my window controller
class MyWindowController: NSWindowController {
init() {
// Some initialization steps below are omitted
let win = NSWindow(...)
super.init(window: win)
let contentView = DropView(frame: win.frame)
win.contentView?.addSubview(contentView)
registerGlobalMouseEvent()
}
func registerGlobalMouseEvent() {
self.window?.acceptsMouseMovedEvents = true
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged, handler: { [self] event in
// Codes below will cause errors
let pasteBoard = NSPasteboard(name: .drag)
guard let fileNames = pasteBoard.propertyList(forType: .init(rawValue: "NSFilenamesPboardType")) as? NSArray else { return }
let changeCount = pasteBoard.changeCount
if fileNames.count > 0 && lastChangeCount != changeCount {
lastChangeCount = changeCount
// My actions when dragging
}
})
}
}
然后我运行我的代码并开始拖动,我得到了三个错误:
[沙盒] 获取沙盒扩展失败
[框架] 无法为 /Users/roy/Downloads/test.txt 发布沙盒扩展,错误 1
[默认] 无法为 URL 颁发沙盒令牌:'file:///Users/roy/Downloads/test.txt' 错误:'Error Domain=NSPOSIXErrorDomain Code=1 "Operation not allowed" UserInfo={NSLocalizedDescription=Cannot issue文件“/Users/roy/Downloads/test.txt”的沙盒扩展:不允许操作}'
但是当我这样做的时候
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged, handler: { [self] event in
// My actions
})
,然后一切顺利。
第一个错误似乎无害,因为它并没有阻止我的应用程序运行。
第二个和第三个是致命的,直接导致我的应用程序崩溃。
我想知道他的代码是否有任何问题?任何有用的想法都会很棒!:)
解决方案
使用 sandbox 时,您需要了解Bookmarks 和 Security Scoped URLs 。拖动的 URL 仅授予您的应用程序进程一次读取或读取/写入“用户选择的文件”的权限,具体取决于您配置权利的方式。
您可以保存书签(数据块)以保持对后续会话的访问,只要该文件没有被另一个进程更新,此时书签变得陈旧并且您需要鼓励用户再次选择该文件。
跨 XPC 边界(如共享)将 URL 传递给另一个进程需要您拥有该文件,因此可能涉及到沙箱缓存的副本。
例如:
let dragurl = url_of_dragged_file //at this point you have at-least read access
let cachepath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).last!
let cachedir = URL(fileURLWithPath: cachepath)
let cacheurl = cachedir
.appendingPathComponent(UUID().uuidString)
.appendingPathExtension(dragurl.pathExtension)
try FileManager.default.copyItem(at: dragurl, to: cacheurl)
此时,您在本地沙盒缓存中有一个副本,可以将其移交给共享表。
推荐阅读
- html - 在日历中保存事件
- css - 如何使用首选颜色方案媒体查询在电子邮件中呈现不同的图标?
- python - printoptions 格式化程序不适用于复数数组的单个元素
- python - 插入重复键更新不工作!而是插入新行?
- r - 添加行的R函数逐行运行但不在函数中
- python - networkx 绘制有向图
- python - 类在python中的所有对象上添加属性
- apache-camel - Apache Camel - 登录路由生成器的 Netty 异常
- wolfram-mathematica - 在 Mathematica 的 BarChart 中包含误差线
- ibm-integration-bus - IBM Integration Bus - 文件输入节点 - 更改 mqsiarchive 文件夹名称/位置