The app is designed to allow the user to select a directory using NSOpenPanel, save access permissions via a security-scoped bookmark, and create a folder in the selected directory using the mkdir bash command executed with Process. The security-scoped bookmark ensures the app can access the directory even after the user closes the app or in subsequent sessions.
However, the code does not work when the App Sandbox is enabled. When the sandbox is removed, the folder creation works without issues. Despite using a security-scoped bookmark to resolve the directory path and access the folder, the app still encounters an "Operation not permitted" error. This indicates that the sandbox restrictions prevent the bash command from operating on the directory, even though permissions should theoretically have been granted via the bookmark.
import SwiftUI
struct ContentView: View {
@State private var folderName: String = ""
@State private var bookmarkData: Data? = nil
@State private var errorMessage: String? = nil
var body: some View {
VStack(spacing: 20) {
TextField("Enter folder name", text: $folderName)
//.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button("Choose Desktop Folder") {
chooseDesktopFolder()
}
Button("Create Folder") {
createFolder()
}
.disabled(bookmarkData == nil || folderName.isEmpty)
if let errorMessage = errorMessage {
Text(errorMessage)
.foregroundColor(.red)
}
}
.padding()
.frame(width: 400, height: 200)
}
private func chooseDesktopFolder() {
let openPanel = NSOpenPanel()
openPanel.canChooseDirectories = true
openPanel.canChooseFiles = false
openPanel.allowsMultipleSelection = false
openPanel.prompt = "Select Folder"
openPanel.begin { response in
if response == .OK, let selectedURL = openPanel.url {
do {
// Create a bookmark from the selected URL
let bookmark = try selectedURL.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
self.bookmarkData = bookmark
self.errorMessage = "Folder selected successfully."
} catch {
self.errorMessage = "Failed to create bookmark: \(error.localizedDescription)"
}
} else {
self.errorMessage = "No folder selected."
}
}
}
private func createFolder() {
guard let bookmarkData = bookmarkData else {
errorMessage = "No folder selected."
return
}
do {
// Resolve the bookmark to get the folder URL
var isStale = false
let folderURL = try URL(resolvingBookmarkData: bookmarkData, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale)
// Start accessing the security-scoped resource
guard folderURL.startAccessingSecurityScopedResource() else {
errorMessage = "Failed to access folder."
return
}
defer { folderURL.stopAccessingSecurityScopedResource() }
// Construct the path of the new folder
let newFolderURL = folderURL.appendingPathComponent(folderName)
// Use bash command to create the folder
let process = Process()
process.executableURL = URL(fileURLWithPath: "/bin/mkdir")
process.arguments = [newFolderURL.path]
try process.run()
process.waitUntilExit()
if process.terminationStatus == 0 {
errorMessage = "Folder created successfully."
} else {
errorMessage = "Failed to create folder with mkdir command."
}
} catch {
errorMessage = "Error: \(error.localizedDescription)"
}
}
}
Since you are accessing the selected files under SIP with write permission, make sure you had enable the read/write
permission in the entitlement.
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
In Xcode, it's <your-target>
-> Signing & Capabilities
-> App Sandbox
-> File Access
, check the option Read/Write
for User Selected Files
.