Created
October 24, 2025 11:45
-
-
Save dehlen/0597dae2677251f2831669bfbfc05503 to your computer and use it in GitHub Desktop.
macOS Sandbox Wrapper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Foundation | |
| import AppKit.NSOpenPanel | |
| class SandboxDirectoryAccess { | |
| static let shared: SandboxDirectoryAccess = SandboxDirectoryAccess() | |
| private var bookmarks = [URL: Data]() | |
| init() {} | |
| func openFolderSelection(then handler: @escaping (URL?) -> Void) { | |
| let openPanel = NSOpenPanel() | |
| openPanel.allowsMultipleSelection = false | |
| openPanel.canChooseDirectories = true | |
| openPanel.canCreateDirectories = true | |
| openPanel.canChooseFiles = false | |
| openPanel.begin { (result) -> Void in | |
| if result == .OK { | |
| if let url = openPanel.urls.first { | |
| self.storeFolderInBookmark(url: url) | |
| } | |
| handler(openPanel.urls.first) | |
| } | |
| } | |
| } | |
| func saveBookmarksData() { | |
| let path = getBookmarkPath() | |
| do { | |
| let data = try NSKeyedArchiver.archivedData(withRootObject: bookmarks, requiringSecureCoding: false) | |
| try data.write(to: path) | |
| } catch { | |
| debugPrint("Could not save bookmark data") | |
| } | |
| } | |
| func loadBookmarks() { | |
| let path = getBookmarkPath() | |
| bookmarks = [:] | |
| if let data = try? Data(contentsOf: path) { | |
| if let unarchived = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) { | |
| bookmarks = unarchived as? [URL: Data] ?? [:] | |
| } | |
| for bookmark in bookmarks { | |
| restoreBookmark(bookmark) | |
| } | |
| } | |
| } | |
| private func storeFolderInBookmark(url: URL) { | |
| do { | |
| let data = try url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil) | |
| bookmarks[url] = data | |
| } catch { | |
| debugPrint("Error storing bookmarks") | |
| } | |
| } | |
| private func getBookmarkPath() -> URL { | |
| let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL | |
| return url.appendingPathComponent("Bookmarks.dict") | |
| } | |
| private func restoreBookmark(_ bookmark: (key: URL, value: Data)) { | |
| let restoredUrl: URL? | |
| var isStale = false | |
| debugPrint("Restoring \(bookmark.key.absoluteString)") | |
| do { | |
| restoredUrl = try URL(resolvingBookmarkData: bookmark.value, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale) | |
| } catch { | |
| debugPrint("Error restoring bookmarks") | |
| restoredUrl = nil | |
| } | |
| if let url = restoredUrl { | |
| if isStale { | |
| debugPrint("URL is stale") | |
| } else { | |
| if !url.startAccessingSecurityScopedResource() { | |
| debugPrint("Couldn't access: \(url.path)") | |
| } | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment