I have been having some issues saving URLs. I want to be able to save a list of URLs with their bookmark data so that the app can still access some folders after reboot. The folders are on the desktop. I have read and write access to the disk, as was set in the app sandbox settings (User Selected File). It works for as long as the app is open but as soon as I restart it the URLs seem to go invalid, or at least it says that I don't have permission to access the folder that is selected. I then have to clear the urls and re-select them.
You can ignore the blacklist thing as I am not using it in the tests I am running. You can also ignore the sources_list and dest_list they are for the GUI. Here is how the user selects the file:
func inputBrowseClicked(source_or_dest: String) {
let inputPanel = NSOpenPanel()
if source_or_dest == "blacklist" {
inputPanel.canChooseFiles = true
inputPanel.canChooseDirectories = false
}
else {
inputPanel.canChooseFiles = false
inputPanel.canChooseDirectories = true
}
let userChoice = inputPanel.runModal()
switch userChoice{
case .OK :
if let inputFileChosen = inputPanel.url {
do {
// Start accessing a security-scoped resource.
_ = inputFileChosen.startAccessingSecurityScopedResource()
let bookmarkData = try inputFileChosen.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
if source_or_dest == "blacklist" {
add_blacklist_file(file: inputFileChosen)
}
else {
add_sources_or_dests_url(url_to_add: bookmarkData, sources_or_dests: source_or_dest)
}
inputFileChosen.stopAccessingSecurityScopedResource()
sources_list = get_sources_or_dests_urls(sources_or_dests: "source")
dest_list = get_sources_or_dests_urls(sources_or_dests: "dest")
}
catch (let error) {
print(error)
return
}
return
}
case .cancel :
return
default:
return
}
return
}
Here is the function that adds one URL to the list:
func add_sources_or_dests_url(url_to_add: Data, sources_or_dests: String) {
// load currently stored list
if var source_dest_urls = userDefaults.array(forKey: "saved_"+sources_or_dests) as? [Data] {
// is the url already in the list
if !(source_dest_urls.contains(url_to_add)){
source_dest_urls.append(url_to_add)
userDefaults.set(source_dest_urls, forKey: "saved_"+sources_or_dests)
userDefaults.set(source_dest_urls.count,forKey: sources_or_dests+"_index")
}
}
else {
userDefaults.set([url_to_add], forKey: "saved_"+sources_or_dests)
userDefaults.set(0,forKey: sources_or_dests+"_index")
}
}
Here is the function of reading the URLs which I use every time I want to access them which is why I don't understand how it can work until I restart the app.
func get_sources_or_dests_urls(sources_or_dests: String) -> [URL] {
// load currently stored list
var source_dest_urls: [URL] = []
if let source_dest_urls_data = userDefaults.array(forKey: "saved_"+sources_or_dests) as? [Data] {
for bookmarkData in source_dest_urls_data {
do {
var isStale = false
let url = try URL(resolvingBookmarkData: bookmarkData, options: [.withSecurityScope], bookmarkDataIsStale: &isStale)
guard !isStale else {
print("Stale URL: "+sources_or_dests)
return source_dest_urls
}
source_dest_urls.append(url)
}
catch (let error) {
print(error)
print(sources_or_dests)
}
}
return source_dest_urls
}
else {
return []
}
}
The funny thing is that when I call the (folder_url).startAccessingSecurityScopedResouce it returns True
Here is an example of the error:
file:///Users/georgeturner/Desktop/Sorted_test/DJI_0274.JPG
2023-06-25 15:20:15.198258+0100 Camera Import[74663:1326092] open on /Users/georgeturner/Desktop/16-07-2022/DJI_0274.JPG: Operation not permitted
Error Domain=NSCocoaErrorDomain Code=513 "“DJI_0274.JPG” couldn’t be copied because you don’t have permission to access “Sorted_test”." UserInfo={NSSourceFilePathErrorKey=/Users/georgeturner/Desktop/16-07-2022/DJI_0274.JPG, NSUserStringVariant=(
Copy
), NSDestinationFilePath=/Users/georgeturner/Desktop/Sorted_test/DJI_0274.JPG, NSFilePath=/Users/georgeturner/Desktop/16-07-2022/DJI_0274.JPG, NSUnderlyingError=0x600002641170 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}