macOS安全书签报错:Error Domain=NSCocoaErrorDomain
macOS安全书签报错:Error Domain=NSCocoaErrorDomain

macOS安全书签报错:Error Domain=NSCocoaErrorDomain

问题描述

在使用安全书签保存NSSavePanel路径时,发现安全书签报错:

书签创建失败: Error Domain=NSCocoaErrorDomain Code=260 "Scoped bookmarks can only be created for existing files or directories" UserInfo={NSURL=file:///Users/fangjunyu/Desktop/%E6%88%AA%E5%B1%8F2025-7-22%2016.8.30.png, NSDebugDescription=Scoped bookmarks can only be created for existing files or directories}

相关代码:

let savePanel = NSSavePanel()
savePanel.allowedContentTypes = [.png]  // 保存图片的格式
savePanel.nameFieldStringValue = fileName   // 保存的文件名称
savePanel.canCreateDirectories = true   // 允许新建文件夹
savePanel.directoryURL = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first!   // 默认保存路径为桌面

savePanel.begin { response in
    if response == .OK {
        if let url = savePanel.url {
            print("url:\(url)")
            // 创建安全书签
            do {
                let bookmark = try url.bookmarkData(options: [.withSecurityScope], includingResourceValuesForKeys: nil, relativeTo: nil)
                UserDefaults.standard.set(bookmark, forKey: "MyFileBookmark")
                print("书签保存成功")
            } catch {
                print("书签创建失败: \(error)")
            }
            
            // 在这里保存文件内容到 url 路径
            print("返回成功,保存图片文件")
            try? imageData?.write(to: url)
        }
    } else {
        print("返回失败")
    }
}

在代码中,我创建NSSavePanel保存文件,并设置默认保存路径为桌面。

当用户保存文件时,NSSavePanel返回保存文件的路径,保存至安全书签。

但实际上发生了这个NSCocoaErrorDomain的报错,报错信息为:

系统只能为“已经存在的文件或目录”创建 安全书签(withSecurityScope)。传入的 url 是一个尚未保存的新文件路径(即将保存),所以不能创建书签。

我输出url,发现url为:

print("url:\(url)") // url:file:///Users/fangjunyu/Desktop/%E6%88%AA%E5%B1%8F2025-7-22%2016.8.30.png

这也就意味着,我尝试将文件的url路径保存到安全书签,而在代码层面,我还没有创建这个文件:

savePanel.begin { response in
    if response == .OK {
        if let url = savePanel.url {
            // 1、创建安全书签
            do {
                let bookmark = try url.bookmarkData(options: [.withSecurityScope], includingResourceValuesForKeys: nil, relativeTo: nil)
                UserDefaults.standard.set(bookmark, forKey: "MyFileBookmark")
                print("书签保存成功")
            } catch {
                print("书签创建失败: \(error)")
            }
            
            // 2、保存文件在创建安全书签之后,还没有保存文件
            try? imageData?.write(to: url)
        }
    } else {
        print("返回失败")
    }
}

因此,发生了试图为一个「还没创建的文件」生成安全书签(Scoped Bookmark)报错。

解决方案

我实际上想要保存的是桌面文件夹的路径,便于后面不再需要用户保存文件的权限,因此应该将桌面文件夹的路径保存到安全书签。

而且,我应该使用NSOpenPanel属性,选择保存的文件夹路径,而不是使用NSSavePanel保存文件,因为NSSavePanel只能获取保存文件的路径。

使用NSOpenPanel保存文件夹的安全书签:

let panel = NSOpenPanel()
panel.canChooseDirectories = true
panel.canChooseFiles = false
panel.allowsMultipleSelection = false
let saveDir = NSLocalizedString("Select the save folder", comment: "选择保存文件夹")
panel.prompt = saveDir

panel.begin { response in
    if response == .OK, let folderURL = panel.url {
        // 创建安全书签
        do {
            let bookmark = try folderURL.bookmarkData(options: [.withSecurityScope], includingResourceValuesForKeys: nil, relativeTo: nil)
            UserDefaults.standard.set(bookmark, forKey: "SaveFolderBookmark")
            print("保存文件夹书签成功:\(folderURL)")
        } catch {
            print("书签创建失败: \(error)")
        }

        let fileURL = folderURL.appendingPathComponent(fileName).appendingPathExtension("png")
        do {
            try imageData?.write(to: fileURL)
        } catch {
            print("保存失败")
        }
    }
}

相关文章

1、macOS安全书签(Security-Scoped Bookmark):https://fangjunyu.com/2025/06/29/macos%e5%ae%89%e5%85%a8%e4%b9%a6%e7%ad%be%ef%bc%88security-scoped-bookmark%ef%bc%89/

2、macOS保存文件的对话框NSSavePanel:https://fangjunyu.com/2025/06/27/macos%e4%bf%9d%e5%ad%98%e6%96%87%e4%bb%b6%e7%9a%84%e5%af%b9%e8%af%9d%e6%a1%86nssavepanel/

3、macOS文件选择对话框NSOpenPanel:https://fangjunyu.com/2025/06/27/macos%e6%96%87%e4%bb%b6%e9%80%89%e6%8b%a9%e5%af%b9%e8%af%9d%e6%a1%86nsopenpanel/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注