startAccessingSecurityScopedResource() 实际上做了什么?

16
我正在制作一个沙盒Mac应用程序,并使用NSOpenPanel获取文件URL,并将其保存到UserDefaults中作为安全作用域书签。当我退出并重新启动应用程序时,我可以将那个数据块解析为URL。
文档说我应该调用startAccessingSecurityScopedResource()并检查其返回值。(当我调用它时,确实会返回true.)但如果我不调用它,我仍然拥有已解析的URL,并且似乎仍然具有访问权限。
startAccessingSecurityScopedResource()实际上是做什么的呢?如果我不调用它,会发生什么不好的事情吗?

2
更新:我在Mac App Store上有一个应用程序已经几个月了,至少有六个不同的版本。这个应用程序从来没有调用过startAccessingSecurityScopedResource(),但是苹果的审核人员和我的用户都没有报告任何访问文件或文件夹的问题。 - Ssswift
2个回答

8
只要您的应用程序仅访问标准位置(下载、音乐、电影、图片),并在应用中包含了所需的程序化文件和文件夹访问的授权,则无需为这些位置存储安全范围的书签。
但是,对于其他位置,在应用程序重新启动后应该保持可访问性,您应该存储安全范围的书签,并在访问之前调用startAccessingSecurityScopedResource()。如果跳过此步骤,则在尝试访问该文件时会出现异常。 startAccessingSecurityScopedResource()使安全范围的书签资源可用于您的应用程序沙盒,从而授予您对该资源的访问权限。

如果你跳过这一步,一旦尝试访问该文件,你将会得到一个异常。就像我在问题中所述,不,我没有遇到这种情况。你是否碰到了这种行为?你正在使用哪个版本的macOS? - Ssswift
1
@Ssswift 这里有一个要复现崩溃的代码片段:https://gist.github.com/anonymous/ef56f55e0e9eb8da8d0514644a5c11b8 (Xcode 9.2,macOS 10.13.3) - seb
谢谢,我有时间会去看一下。从你的代码一瞥之间,我发现你正在使用"/tmp",这在Mac沙盒中是一个有趣的情况,因为它是指向"/private"的符号链接。如果你尝试在沙盒中使用/tmp,很多事情会表现得非常奇怪。 - Ssswift
5
我也遇到了这个问题,一开始并不清楚所有的工作原理。我在这里写了一篇博客:https://benscheirman.com/2019/10/troubleshooting-appkit-file-permissions/ - Ben Scheirman

1

startAccessingSecurityScopedResource 是在 macOS 和 iOS 上用于访问安全范围资源的方法。这些资源指的是由于安全限制而无法直接访问的文件或目录,例如 App Group 容器中的文件位置或系统受保护位置中的文件。

startAccessingSecurityScopedResource 方法用于请求对这些范围安全资源的临时访问权限,允许您的应用程序在有限的时间内访问它们,通常是直到应用程序完成与资源的工作为止。这对于确保您的应用程序可以在不违反系统安全限制的情况下使用这些资源非常有用。

例如,.kml 文件的路径如下:

file:///private/var/mobile/Containers/Shared/AppGroup/XXXXXXXX/File%20Provider%20Storage/example_file.kml

记住,在使用资源完成后,使用stopAccessingSecurityScopedResource停止访问资源是非常重要的,这样可以释放资源并保持良好的安全和权限管理。
下面是一个简单的使用示例:
import Foundation

// Get the URL of the file within the App Group container
if let fileURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "com.yourcompany.yourappgroup")?.appendingPathComponent("example_file.kml") {
    
    // Request temporary access to the security-scoped resource
    let accessGranted = fileURL.startAccessingSecurityScopedResource()
    
    if accessGranted {
        do {
            // Safely access the file
            let fileContents = try String(contentsOf: fileURL, encoding: .utf8)
            print("File contents: \(fileContents)")
        } catch {
            print("Error reading the file: \(error.localizedDescription)")
        }
        
        // Stop accessing the resource after use
        fileURL.stopAccessingSecurityScopedResource()
    } else {
        print("Failed to obtain access to the security-scoped resource.")
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接