belovachap
belovachap

Reputation: 29

Swift FileManager.default.copyItem(at: URL, to: URL) folder permission error

I'm writing a small Mac OS X Desktop application that copies a random sampling of files from a source folder to a destination folder, see Select-Random-Files.

The code that's giving me the most trouble at the moment is the FileManager.default.copyItem method. I get the error couldn't be copied because you don't have permission to access even when I choose folders in my Documents directory that appear to have read/write permissions for my user.

Here's the relevant code:

//
//  ContentView.swift
//  Select Random Files
//
//  Created by Chapman on 6/29/24.
//

import SwiftUI

struct ContentView: View {
    @State var sourceFolder: URL? = nil
    @State var destinationFolder: URL? = nil

    var body: some View {
        VStack {
            Button("Choose Source Folder") {
                self.selectSourceFolder()
            }
            Button("Choose Destination Folder") {
                self.selectDestinationFolder()
            }
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Button(action: {
                var files = [URL]()
                if let enumerator = FileManager.default.enumerator(at: sourceFolder!, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) {
                    for case let fileURL as URL in enumerator {
                        do {
                            let fileAttributes = try fileURL.resourceValues(forKeys:[.isRegularFileKey])
                            if fileAttributes.isRegularFile! {
                                files.append(fileURL)
                            }
                        } catch { print(error, fileURL) }
                    }
                    print(files)
                }
                files = Array(files.shuffled().prefix(3))
                for f in files {
                    let dst = destinationFolder!.appendingPathComponent(f.lastPathComponent)
                    do { try FileManager.default.copyItem(at: f, to: dst)
                    } catch { print(error, f) }
                }
            }, label: {
                Text("Copy")
            })
        }
        .padding()
    }
    
    func buildFolderPicker() -> NSOpenPanel {
        let folderChooserPoint = CGPoint(x: 0, y: 0)
        let folderChooserSize = CGSize(width: 500, height: 600)
        let folderChooserRectangle = CGRect(origin: folderChooserPoint, size: folderChooserSize)
        let folderPicker = NSOpenPanel(contentRect: folderChooserRectangle, styleMask: .utilityWindow, backing: .buffered, defer: true)
        
        folderPicker.canChooseDirectories = true
        folderPicker.canChooseFiles = true
        folderPicker.allowsMultipleSelection = true
        folderPicker.canDownloadUbiquitousContents = true
        folderPicker.canResolveUbiquitousConflicts = true
        return folderPicker
    }

    func selectSourceFolder() {
        let folderPicker = buildFolderPicker()
        folderPicker.begin { response in
            if response == .OK {
                sourceFolder = folderPicker.url
            }
        }
    }
    
    func selectDestinationFolder() {
        let folderPicker = buildFolderPicker()
        folderPicker.begin { response in
            if response == .OK {
                destinationFolder = folderPicker.url
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

And a screen shot of clicking the "Copy" button with console output about permission errors:

enter image description here

I've tried Googling this issue and there don't appear to be many examples of solutions for my problem.

Upvotes: 1

Views: 85

Answers (1)

belovachap
belovachap

Reputation: 29

We figured it out!! I only had read-only entitlements set, needed to be read-write! Here's the line that fixed it all: https://github.com/belovachap/Select-Random-Files-Mac/blob/main/Select%20Random%20Files/Select_Random_Files.entitlements#L7

Upvotes: 0

Related Questions