我有一個本機 macOS 應用程式 Messer,它允許轉換/調整大小/填充影像檔案。我內置的一項功能是自動轉換特定檔案夾中的檔案。
此功能適用于大多數檔案夾,即使它可能需要權限才能訪問它們。例如,選擇Downloads要自動轉換的檔案夾會觸發用戶授予訪問權限的權限對話框。
檔案夾也是如此Desktop,但是,即使已授予該Desktop檔案夾的權限,嘗試在子目錄中復制檔案時也會出現錯誤。
錯誤輸出:
2022-04-27 13:35:04.255243 0200 Messer[1254:11983] open on /Users/osp/Desktop/posts/a-plus-content-4.png: Operation not permitted
Messer, could not copy file Error Domain=NSCocoaErrorDomain Code=513 "“a-plus-content-4.png” couldn’t be copied because you don’t have permission to access “com.ospfranco.messer”." UserInfo={NSSourceFilePathErrorKey=/Users/osp/Desktop/posts/a-plus-content-4.png, NSUserStringVariant=(
Copy
), NSDestinationFilePath=/var/folders/qn/vyvn49j90jv9_77vq77wzvw00000gn/T/com.ospfranco.messer/a-plus-content-4.png, NSFilePath=/Users/osp/Desktop/posts/a-plus-content-4.png, NSUnderlyingError=0x60000206dda0 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
當我嘗試將檔案復制到臨時目錄時拋出:
func secureCopyItem(at srcURL: URL, to dstURL: URL) {
do {
if FileManager.default.fileExists(atPath: dstURL.path) {
try FileManager.default.removeItem(at: dstURL)
}
try FileManager.default.copyItem(at: srcURL, to: dstURL)
} catch let error {
print("Messer, could not copy file \(error)")
SentrySDK.capture(error: error)
}
}
在這里您可以看到該應用程式具有完整的磁盤訪問權限:

然而應用程式仍然崩潰!如果我選擇任何其他檔案夾,復制操作將正常作業。所有的權利和權限似乎都在那里。知道有什么問題嗎?
編輯1:
似乎不太清楚我是否真的從桌面 URL 復制到臨時目錄,所以這里是一些周圍的代碼:
if url.isImage && url.isLocalFile {
let newFileUrl = FileConstants.tempUrl.appendingPathComponent(url.lastPathComponent)
FileManager.default.secureCopyItem(at: url, to: newFileUrl)
self.initPipeline(urls: [newFileUrl], autoSave: true)
}
不同常量檔案中的臨時 URL:
static let tempUrl: URL = {
return FileManager.default.temporaryDirectory
}()
我可以向您保證,與另一個目錄中的另一個檔案(例如,下載)一起運行的相同代碼是正確的,并且可以正常運行而不會出現任何錯誤。
編輯2:
在閱讀了一些其他答案之后,我訪問資源的方式可能存在問題,我允許用戶通過 UI 選擇一個檔案夾,然后將此路徑保存在我的應用程式中。但是,由于權限的原因,資源可能只能在用戶選擇檔案夾后的一段時間內訪問,而不是無限期地訪問。因此,當我嘗試訪問檔案夾中的資源一段時間后,macOS 只會阻止我讀取檔案的任何嘗試。
我嘗試使用一些資源鎖定方法,它在傳遞的 URL 上回傳 false:
let scopedResourceLocked = url.startAccessingSecurityScopedResource()
print("SCOPED RESOURCE LOCKEd \(scopedResourceLocked)") // prints false
let newFileUrl = FileConstants.tempUrl.appendingPathComponent(url.lastPathComponent)
FileManager.default.secureCopyItem(at: url, to: newFileUrl)
url.stopAccessingSecurityScopedResource()
編輯3:
我只是嘗試重新選擇檔案夾(通過 NSOpenPanel)并轉換一個檔案,它作業。所以我想如果沒有用戶互動,就沒有辦法以一致的方式實作這一點。一段時間后,macOS 將再次鎖定/保護檔案夾中的檔案。
uj5u.com熱心網友回復:
非常感謝@vadian 為我指明了正確的方向。事實證明,擁有完整的磁盤訪問權限是不夠的,即使用戶已授予特定檔案夾的權限。
從 NSOpenPanel 獲取 URL 后,您需要創建一個 Bookmark 并保存二進制資料。在進一步打開應用程式時,您可以對二進制資料進行水合。從此書簽物件中,您可以再次創建一個 URL,您需要在該 URL 上呼叫startAccessingSecurityScopedResource并stopAccessingSecurityScopedResource訪問用戶已授予訪問權限的任何先前檔案夾(即使您正在訪問該檔案夾內的檔案或子檔案夾。
基本上遵循本教程:

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/468649.html
下一篇:我無法解決這個錯誤“lateinitpropertydataBindinghasnotbeeninitialized”
