当前位置: 首页 > 知识库问答 >
问题:

捕获从磁盘读取文件时出错-您没有权限

郎喜
2023-03-14

我在AppDel中使用以下代码。这是在用户点击gpx文件或使用共享选项与我的应用程序共享文件时触发的。此时是用户指定他们允许我的应用程序访问该文件,所以我有点困惑为什么这仍然被拒绝。非常感谢任何建议。

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
    
    if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
        let fileURL = dir.appendingPathComponent(url.lastPathComponent)
        if FileManager.default.fileExists(atPath: fileURL.path) {
            print("File already exists")
        }
        else {
            do {
                try FileManager.default.copyItem(at: url, to: fileURL)
                print("Did write file to disk")
            }
             catch {
                 DispatchQueue.main.async(){
                         print("Catch error writing file to disk: \(error)")
                 }
             }
        }
    }
    return true
}

错误打印到控制台,如下所示:

Error Domain=NSCocoaErrorDomain Code=257"无法打开文件"Beech_Hill_Long_Route.gpx",因为您无权查看它。"用户信息={NSFilePath=/Private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Beech_Hill_Long_Route.gpx, NSUnderlyingError=0x282c19a70{Error Domain=NSPOSIXErrorDomain Code=1"不允许操作"}}

共有1个答案

孙明德
2023-03-14

我对这在iOS上的具体工作方式知之甚少,但我确实对它在macOS上的工作方式有所了解,这两者应该是相似的。对于macOS沙盒应用程序,用户必须特别通过NSOpenPanel或NSSavePanel选择沙盒外部的文件。iOS上的等价物是UIDocumentPickerViewController,但我认为显式共享也会起作用。基于此,如果我面对你的问题,我会怎么想,我会尝试什么:

在调用FileManager时,您有两个URL。违约copy()。不清楚是哪一个产生了错误,所以我会同时考虑这两个。

首先让我们看看fileURL。您正在构建它以将文件放入用户的Documents目录中。至少在macOS上,该目录不在应用程序的沙盒中,这意味着通过NSSaveBoard询问用户(这也意味着他们可能决定将其放在其他地方)。您可能必须执行UIKit等效操作,或者只是确保您选择的位置在您的沙盒中。

要测试这一点,请尝试写入文件URL,而不是进行复制,以仅隔离该文件。例如:

do { try "TestString".data(using: .utf8)?.write(url: fileURL) }
catch { print("Write failed: \(error.localizedDescription)") }

如果失败,那么您的问题是文件URL,在这种情况下,您可能需要使用UIDocumentPickerViewController来保存它,或者选择一个肯定位于应用程序沙盒中的位置。

如果测试成功,则问题一定出在传入的URL上。

我将假设url已经是安全范围内的,因为我不确定共享在其他情况下如何工作。我认为最可能发生在幕后的是,当用户与你的应用程序共享URL时,iOS会从URL创建一个安全范围的书签,并将书签而不是URL发送到你的应用程序。然后在你的应用程序端,该书签用于在将其传递给你的应用程序的代理之前重新构建URL。如果我说得对,您需要打开和关闭一个安全作用域才能使用它:

url.startAccessingSecurityScopedResource()

// access your file here

url.stopAccessingSecurityScopedResource()

请注意,必须在主线程上调用stopAccessingSecurityScopeResource(),因此,如果代码是异步发生的,则需要安排它在那里运行:

url.startAccessingSecurityScopedResource()

// access your file here

DispatchQueue.main.async { url.stopAccessingSecurityScopedResource() }

如果您需要保存URL本身以便在将来的程序运行中使用。。。您不能。嗯,您可以,但它无效,因此您将立即返回权限错误。相反,您必须保存一个书签,然后在以后的运行中,从书签重建URL。

let bookmark = try url.bookmarkData(
    options: .withSecurityScope, 
    includingResourceValuesForKeys: nil, 
    relativeTo: nil
)

书签是数据的一个实例,因此您可以将其写入到用户默认值或任何您想保存它的地方。要稍后从中获取URL,请执行以下操作:

var isStale = false
let url = try URL(
    resolvingBookmarkData: bookmark, 
    options: .withSecurityScope, 
    relativeTo: nil, 
    bookmarkDataIsStale: &isStale
)

if isStale 
{
    let newBookmark = try url.bookmarkData(
        options: .withSecurityScope, 
        includingResourceValuesForKeys: nil, 
        relativeTo: nil
    )
    // Save the new bookmark
}

请注意,如果初始值设定项返回后,isStale为true,则需要重新制作并重新保存书签。

很遗憾我们不得不经历这么多麻烦,但我们生活在一个有些人坚持对他人的设备和数据做坏事的世界里,所以这是我们必须处理的,以保护用户免受恶意数据泄露。

 类似资料:
  • 问题内容: 我已经从互联网上下载了一个项目,当我尝试运行/构建XCode时,XCode说: 无法打开文件“项目名称”,因为您无权查看该文件。 我还对项目文件夹设置了读/写权限,但仍然无法正常工作。 为什么会这样呢?请帮我解决这个问题 问题答案: 转到Finder中包含项目的文件夹。 右键单击>获取信息 转到“信息”窗格的底部,然后单击小锁,在出现提示时输入密码。 然后,更改您自己的读写权限。 单击

  • 需要帮助修复此错误。我试图打印出字符串国家名称的数组长度。 我从一个简历文件阅读,我一直得到上面的错误。下面是我的代码: 下面是我的TestCSV类文件: 我的csv文件如下所示:这是一个摘要,因为我不想打印出全部252个国家。基本上,我把252个国家的数据存储在一个字符串数组中,年份存储在一个整数数组中,每个国家的蜂窝数据统计数据存储在一个二维双数组中。我是编程新手,我想知道我的方向是否正确,如

  • 问题内容: 我有一个数据结构,我希望能够在关闭程序之前写入文件,然后在下次应用程序启动时从文件中读取数据以重新填充该结构。 我的结构是。对象很简单;对于成员变量,它具有一个String和两个布尔类型的小型本机数组。这是一个真正简单的应用程序,我希望一次不会超过10-15 对。 我一直在尝试(不成功)对象输入/输出流。我需要使对象类可序列化吗? 您能给我一些最好的建议吗?我只需要向正确的方向推进即可

  • 我正在尝试创建一个游戏的主菜单,我的朋友和我正在尝试制作。我们使用Eclipse+LibGdx,我真的不知道我在做什么。我使用的是直接从的代码,我已经无法在任何博客/论坛/教程上找到任何帮助。(http://www.gamefromscratch.com/post/2015/02/03/libgdx-video-tutorial-scene2d-ui-widgets-layout-and-skin

  • 我试图读取CSV文件,但它抛出了一个错误。我无法理解我的语法有什么问题,或者我是否需要向我的read_csv添加更多属性。 我试了一下这个解决办法 UnicodeDecodeError:“utf-8”编解码器无法解码位置21中的字节0x96:起始字节也无效。但它不起作用 [错误] UnicodeDecodeError回溯(最近一次调用)pandas/_libs/解析器。大熊猫中的pyx_图书馆。解

  • 我在apache Spark中读取本地文件时出错。scala>val f=sc.textfile(“/home/cloudera/downloads/sample.txt”)