代码之家  ›  专栏  ›  技术社区  ›  juanmartin

无法修改iOS应用程序沙盒之外的文件。权限问题

  •  0
  • juanmartin  · 技术社区  · 1 年前

    我正在开发一个iOS应用程序(最新的Swift、iOS、Xcode版本的atm写作),它需要重命名位于任何地方(本地存储、外部存储、云等)的音频文件(稍后修改其元数据)。

    当试图重命名某个文件夹中的文件时,在物理设备上进行测试时会出现问题 在我的iPhone上 ,该应用程序在模拟器上测试时按预期操作。在我的实体iPhone上,我收到一个错误日志,说我没有权限这样做。

    “filename.mp3” couldn’t be moved because you don’t have permission to access “randomFolder".

    我在谷歌上搜索并询问了GPT,了解了 FileCoordinator , UIDocumentPickerViewController , startAccessingSecurityScopedResource 。我也看到了 this video ,并最终遵循了这一点 other one .

    我有一些代码:

    这是文档选择器,然后我从 .sheet 在另一个视图上。

    struct DocumentPicker: UIViewControllerRepresentable {
        @Binding var newName: String
        @EnvironmentObject private var bookmarkController: BookmarkController
        
        func makeUIViewController(context: Context) -> UIDocumentPickerViewController {
            let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: supportedTypes)
            documentPicker.delegate = context.coordinator
            return documentPicker
        }
        
        func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {
            print("updateUIViewController documentPicker")
        }
    
        func makeCoordinator() -> Coordinator {
            Coordinator(self, newName)
        }
    
        class Coordinator: NSObject, UIDocumentPickerDelegate {
            var parent: DocumentPicker
            var newName: String
            
            init(_ parent: DocumentPicker, _ newName: String = "") {
                self.parent = parent
                self.newName = newName
            }
            
            func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
                // save bookmark
                print("documentPicker \(urls[0])")
                parent.bookmarkController.addBookmark(for: urls[0])
                
                // Rename the file
                var error: NSError?
                
                NSFileCoordinator().coordinate(readingItemAt: urls[0], options: [], error: &error) { coordinatedURL in
                    do {
                        //                let data = try Data(contentsOf: newURL)
                        print("urls[0]: \(urls[0])")
                        print("coordinatedURL: \(coordinatedURL)")
                        print("renamedURL: \(newName)")
                        try renameFile(at: coordinatedURL, to: newName)
    } catch  {
                        print("Error: \(error.localizedDescription)")
                    }   
                }
            }
        }
    }
    
    

    重命名功能:

    
    /// Rename selected file from browser
    func renameFile(at fileURL: URL, to newName: String) throws {
        let fileExtension = fileURL.pathExtension
        let directory = fileURL.deletingLastPathComponent()
    
        // Create a new URL with the updated name and the original extension
        let renamedURL = directory.appendingPathComponent(newName).appendingPathExtension(fileExtension)
    
        try FileManager.default.moveItem(at: fileURL, to: renamedURL)
    }
    

    我有一个 BookmarkController 与我上面提到的第二个视频中的位置相同,这样我的URL就会被标记为书签以供以后使用。它在这里:

    import SwiftUI
    import MobileCoreServices
    
    class BookmarkController: ObservableObject {
        @Published var urls: [URL] = []
        
        init() {
            loadAllBookmarks()
        }
        
        func addBookmark(for url: URL) {
            print("adding bookmark for \(url)")
            do {
                guard url.startAccessingSecurityScopedResource() else {
                    print("Failed to obtain access to the security-scoped resource.")
                    return
                }
                
                defer { url.stopAccessingSecurityScopedResource() }
                
                let bookmarkData = try url.bookmarkData(options: .minimalBookmark, includingResourceValuesForKeys: nil)
                
                let uuid = UUID().uuidString
                try bookmarkData.write(to: getAppSandboxDir().appendingPathComponent(uuid))
                
                urls.append(url)
            } catch {
                print("Error Adding Bookmark: \(error.localizedDescription)")
            }
        }
        
        func loadAllBookmarks() {
            // Get all the bookmark files
            let files = try? FileManager.default.contentsOfDirectory(at: getAppSandboxDir(), includingPropertiesForKeys: nil)
            // Map over the bookmark files
            self.urls = files?.compactMap { file in
                do {
                    let bookmarkData = try Data(contentsOf: file)
                    var isStale = false
                    // Get the URL from each bookmark
                    let url = try URL(resolvingBookmarkData: bookmarkData, bookmarkDataIsStale: &isStale)
                    
                    guard !isStale else {
                        // Handle stale bookmarks
                        return nil
                    }
                    print("loaded bookmark: \(url)")
                    // Return URL
                    return url
                } catch {
                    print("Error Loading Bookmark: \(error.localizedDescription)")
                    return nil
                }
            } ?? []
        }
        
        private func getAppSandboxDir() -> URL {
            // TODO ver 0 index
            FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        }
    }
    
    

    在我的设备上运行时,我看到 url.startAccessingSecurityScopedResource 投掷:

    Failed to obtain access to the security-scoped resource.

    我还尝试过访问父目录,如下所示:

    let parentURL = url.deletingLastPathComponent()

    然后使用 parentURL 相反,它也失败了。


    我注意到我的应用程序没有显示在 设置->隐私&安全性->文件和文件夹 列表在用户同意的情况下,我的应用程序没有触发任何对话框添加到此处。

    在中玩弄权利 Info.plist 和Capabilities也没有帮助,但我不太确定应该添加哪些。

    所以:

    我看到的权限问题和我的应用程序没有出现在iPhone的“文件和文件夹”隐私设置中,可能是因为我的应用是用不在苹果开发者程序中的开发者帐户签名的吗?这是我最后的想法,因为我不明白我还应该尝试什么。

    任何建议和帮助都将不胜感激。 谢谢

    0 回复  |  直到 1 年前