我在我的应用程序中启动应用程序之间的文件夹“重用”安全范围 URL 书签时遇到问题(在 Mojave 和 Catalina 上)。
libarchive
它是使用框架的简单解压缩应用程序。用户选择要解压的文件,我想为其父文件夹存储 URL 书签(例如 ~/Desktop),并在下次用户尝试解压缩同一文件夹中的文件时重用它。
首先,我在我的应用程序的权利文件中添加了以下内容:
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.bookmarks.app-scope</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
首次访问文件(分别为父文件夹)时:
- 用户选择要解压的文件
- 我提出
NSOpenPanel
获得对文件夹的访问权限:
let directoryURL = fileURL.deletingLastPathComponent()
let openPanel = NSOpenPanel()
openPanel.allowsMultipleSelection = false
openPanel.canChooseDirectories = true
openPanel.canCreateDirectories = false
openPanel.canChooseFiles = false
openPanel.prompt = "Grant Access"
openPanel.directoryURL = directoryURL
openPanel.begin { [weak self] result in
guard let self = self else { return }
// WARNING: It's absolutely necessary to access NSOpenPanel.url property to get access
guard result == .OK, let url = openPanel.url else {
// HANDLE ERROR HERE ...
return
}
// We got URL and need to store bookmark's data
// ...
}
- 我获取文件夹URL 的书签数据并将其存储到密钥存档:
let data = try url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
bookmarks[url] = data
NSKeyedArchiver.archiveRootObject(bookmarks, toFile: bookmarksPath)
- 现在我开始使用文件URL 并将
libarchive
.zip 文件解压缩到它的父文件夹:
fileURL.startAccessingSecurityScopedResource()
// Decompressing file with libarchive...
fileURL.stopAccessingSecurityScopedResource()
- 一切都按预期工作,.zip 文件被解压缩
重新启动应用程序时,在同一文件夹中解压缩文件,重用保存的书签数据:
- 我从键控存档中获取书签:
let bookmarks = NSKeyedUnarchiver.unarchiveObject(withFile: bookmarksPath) as? [URL: Data]
- 我从文件父文件夹的书签中获取书签数据并解决它:
let directoryURL = fileURL.deletingLastPathComponent()
let data = bookmarks[directoryURL]!
var isStale = false
let newURL = try URL(resolvingBookmarkData: data, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale)
- 现在我再次开始使用文件URL 并使用
libarchive
将 .zip 文件解压缩到它的父文件夹:
fileURL.startAccessingSecurityScopedResource()
// Decompressing file with libarchive...
fileURL.stopAccessingSecurityScopedResource()
但是这次libarchive
返回错误说Failed to open \'/Users/martin/Desktop/Archive.zip\'
我知道我可能做错了什么或者不理解安全范围 URL 书签的概念,但找不到问题所在。有什么提示吗?
最终解决方案
Rckstr 在这个 Apple 开发者论坛帖子中的回答和回答都为我指明了正确的方向。绝对有必要调用startAccessingSecurityScopedResource()
由返回的 URL 的相同实例try URL(resolvingBookmarkData: data, options: .withSecurityScope ...