【问题标题】:NSCocoaErrorDomain Code=257 File PermissionNSCocoaErrorDomain 代码=257 文件权限
【发布时间】:2021-08-30 18:58:15
【问题描述】:

在尝试使用包装 UIDocumentPickerViewController 的 UIViewControllerRepresentable 在 Swift UI 应用程序中获取文件时,我遇到了一个非常奇怪的行为:

在模拟器上运行应用程序按预期工作。但是,在物理设备上运行应用程序不会返回文件。相反,它会抛出以下错误:Error Domain=NSCocoaErrorDomain Code=257 "无法打开文件“grile.doc”,因为您无权查看它。"

调试,我设法发现导致物理设备上抛出此错误的代码块不是对文件的实际访问,而是试图获取抛出的文件大小。

我在这里做错了什么,这使得 Representable 在模拟器上工作得很好,但在物理设备上却不能工作?

我已经尝试使用 FileManager 方法来获取文件大小,同样的事情发生了。我还尝试使用 FileManager 将文件复制到临时位置,这也会引发相同的错误。

import Foundation
import SwiftUI
import UniformTypeIdentifiers

struct FilePicker: UIViewControllerRepresentable {
    
    // MARK: - Properties
    var didPickFileURL: ((URL) -> Void)
    var didPickFileOverFileSizeLimit: (() -> Void)
    
    // MARK: - UIViewController Wrapper Methods
    func makeUIViewController(context: Context) -> UIDocumentPickerViewController {
        let picker = UIDocumentPickerViewController(forOpeningContentTypes: [UTType("public.item")!])
        picker.allowsMultipleSelection = false
        picker.delegate = context.coordinator
        return picker
    }
    
    func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {
    }
    
    func makeCoordinator() -> Coordinator {
        return FilePicker.Coordinator(parent: self)
    }
    
    
    // MARK: - Coordinator
    class Coordinator: NSObject, UIDocumentPickerDelegate {
        
        // MARK: - Coordinator Properties
        var parent: FilePicker
        
        
        // MARK: - Coordinator Init
        init(parent: FilePicker) {
            self.parent = parent
        }
        
        
        // MARK: - Coordinator UIDocument Delegate
        func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
            guard let url = urls.first else { return }
            
            do {
                let resources = try url.resourceValues(forKeys:[.fileSizeKey])
                let fileSize = Double(resources.fileSize!)
            
                // check if the file size is bigger than the limit per attachment
                if fileSize.convertBytesToMegabytes() < 10 {
                    self.parent.didPickFileURL(url)
                } else {
                    self.parent.didPickFileOverFileSizeLimit()
                }
            } catch {
                print("Error: \(error)")
            }
        }
    }
}

转换扩展:

extension Double { 
    func convertBytesToMegabytes() -> Double {
        let kilobytes = self / 1024
        let megabytes = kilobytes / 1024
        return megabytes
    }
}

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    我也遇到过问题。如果您查看文档的 URL,您可以尝试:

    url.startAccessingSecurityScopedResource()
    

    如果返回 true,您还需要调用:

    url.stopAccessingSecurityScopedResource()
    

    【讨论】:

      猜你喜欢
      • 2021-05-11
      • 1970-01-01
      • 2019-06-28
      • 2021-04-14
      • 2012-04-23
      • 1970-01-01
      • 2020-02-23
      • 2017-06-16
      • 2018-08-18
      相关资源
      最近更新 更多