如何从 Swift 中的字符串路径访问安全范围资源?

Posted

技术标签:

【中文标题】如何从 Swift 中的字符串路径访问安全范围资源?【英文标题】:How to access a Security Scoped Resource from a String Path in Swift? 【发布时间】:2021-07-29 23:31:17 【问题描述】:

我目前正在使用 Flutter 将有效文件路径的 String 传递给 Swift,以便访问 安全范围资源 (这部分可能不相关)

所以我有一个接受String 的函数,如下所示:

public func requestAccessToFile(filePath: String) -> Bool 
  let fileUrl = URL(fileURLWithPath: filePath)
  return fileUrl.startAccessingSecurityScopedResource()

我知道startAccessingSecurityScopedResource 并不总是返回true,但在这种情况下,它应该返回,因为如果我尝试访问文件而不返回true,则会出现权限错误。

更多上下文:如果我从文件选择器获取 URL 后立即调用 startAccessingSecurityScopedResource,它确实会成功,但如果我使用函数执行它会失败(请注意该函数被调用带有String 并且我正在传递没有file:// 协议的路径。例如"/private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Documents/afile.pdf"

所以我的猜测是文件选择器创建的 URL 与我使用字符串路径创建的 URL 有所不同。但不确定。

提前感谢您的帮助。

【问题讨论】:

啊,一个额外的评论,它确实在模拟器上工作,它只在物理设备上失败。 【参考方案1】:

UIDocumentPickerViewController 提供了一个安全范围的 URL 来访问资源,并且不可能从字符串路径中创建相同的 URL:

如果您需要将安全范围 URL 的路径作为字符串值(由 path 方法提供),例如提供给需要字符串值的 API,请根据需要从 URL 获取路径。但是请注意,从安全范围 URL 获取的基于字符串的路径不具有安全范围,您不能使用该字符串来获取对安全范围资源的访问权限。 https://developer.apple.com/documentation/foundation/nsurl

如果您需要在代码中保存或共享安全资源的位置,您应该使用书签:

// Get bookmark data from the provided URL
let bookmarkData = try? pickedURL.bookmarkData()
if let data = bookmarkData 
    // Save data
    ...


...

// Access to an external document by the bookmark data
if let data = bookmarkData 
    var stale = false
    if let url = try? URL(resolvingBookmarkData: data, bookmarkDataIsStale: &stale),
       stale == false,
       url.startAccessingSecurityScopedResource()
    
        var error: NSError?
        NSFileCoordinator().coordinate(readingItemAt: url, error: &error)  readURL in
            if let data = try? Data(contentsOf: readURL) 
                ...
            
        
        
        url.stopAccessingSecurityScopedResource()
    

【讨论】:

谢谢!今天会检查书签部分。

以上是关于如何从 Swift 中的字符串路径访问安全范围资源?的主要内容,如果未能解决你的问题,请参考以下文章

如何从Swift中的Cloud FireStore Firebase访问特定字段

如何在 Documents 文件夹中保存 UIImagePicker 中的 UIImage 并获取路径字符串以保存在 Swift 中的 Core Data 中

如何从 Swift 中的 UITextView 获取链接范围

如何从 AWS 胶水访问 VPC 中的 aws 资源?

Swift 4:从 DispatchQueue.main(范围)访问变量

如何从 swift 代码中应用 firebase 数据库安全规则