Search code examples
swiftmacosswiftui

Mac app can't write to Sandboxed Documents Directory


I have the following function to copy a file to a specific folder inside the documents directory of my Sandboxed app:

extension FileManager {
    func copy(file: URL, to directory: Directory) throws -> URL {
        let documentsDirectory = URL.documentsDirectory
        let targetFolder = documentsDirectory
            .appendingPathComponent(directory.rawValue)
    
        if !fileExists(atPath: targetFolder.path()) {
            try createDirectory(at: targetFolder, withIntermediateDirectories: false)
        }
    
        let destinationURL = targetFolder
           .appendingPathComponent(file.lastPathComponent)
        try self.copyItem(at: file, to: destinationURL)
    
        return destinationURL
    }
}

The file I'm trying to copy is obtained by swiftUI's fileImporter:

.fileImporter(isPresented: $filePickerOpen, allowedContentTypes: [.item]) { result in
    guard case let .success(fileUrl) = result else {
        return
    }            
    fm.copy(file: fileUrl, to: .someDir)
}

But it fails saying I don't have permission to access someDir. The weird thing for me is that the directory someDir is created in the Documents folder so my app clearly has access to it's documents directory (I just mention that because I've read answers on other questions that it may be a bug with the changing entitlements over time)

Edit:

To make it more clear, the copy function is in a FileManager extension and Directory is an enum with some predefined directory names


Solution

  • Apparently the error is misleading, because even though it explicitly mentions that my app can not access the target directory, the issue was actually with my source file. Adding the following to the begging of my copy function solved the issue:

    guard file.startAccessingSecurityScopedResource()
    else { throw FileError.noPermission }
    defer {
       file.stopAccessingSecurityScopedResource()
    }