UIDocumentPickerViewController选择文件夹并在将来写入文件到该文件夹

本文的文案由GPT4生成

在 iOS 开发中,我们有时需要让用户选择一个文件夹路径,用于保存或读取文件。但是选择过的文件夹路径在下次使用时,我们希望用户不需要再次选择。这篇博客将带你了解如何使用 UIDocumentPickerViewController 界面来获取文件的路径,包含 iCloud 中的文件夹路径,以及将这些路径存储为 bookmark,方便根据这些路径直接进行文件的读写,而无需让用户再次进行选择。

使用 UIDocumentPickerViewController 获取选择的文件夹路径

首先,创建并弹出 UIDocumentPickerViewController,设置 documentTypes 为 ["public.folder"] 以只选择文件夹:

let documentPicker = UIDocumentPickerViewController(documentTypes: ["public.folder"], in: .open)
documentPicker.delegate = self
let rootViewController = UIApplication.shared.delegate?.window??.rootViewController
rootViewController?.present(documentPicker, animated: true, completion: nil)

然后,实现 UIDocumentPickerDelegate 协议,通过 documentPicker(_:didPickDocumentsAt:) 方法来获取用户选择的文件夹路径:

func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
    guard let pickedURL = urls.first else {
        return
    }
    
    // 处理 pickedURL
}

将选择的文件夹路径存储为 Bookmark

通过 UIDocumentPickerViewController 获取到文件夹路径后,我们需要将其存储为 bookmark。整个过程需要在 startAccessingSecurityScopedResource 和 stopAccessingSecurityScopedResource 之间进行:

let isAccessing = pickedURL.startAccessingSecurityScopedResource()
if !isAccessing {
    // 无法访问文件夹
    return
}
let bookmarkData = try pickedURL.bookmarkData(options: NSURL.BookmarkCreationOptions.minimalBookmark, includingResourceValuesForKeys: nil, relativeTo: nil)
pickedURL.stopAccessingSecurityScopedResource()

将生成的 bookmarkData 转换为 base64 编码的字符串,方便存储:

let bookmarkDataString = bookmarkData.base64EncodedString(options: [])

将 bookmarkDataString 保存到本地(如:UserDefaults)即可。

使用 Bookmark 写入文件

当我们需要将文件写入到之前选择的文件夹路径时,首先需要将存储的 bookmarkDataString 转换为 URL:

guard let bookmarkData = Data(base64Encoded: bookmarkDataString, options: []) else {
    // 处理无效的 bookmarkDataString
    return
}
var isStale = false
let directoryURL = try? URL(resolvingBookmarkData: bookmarkData, options: .withoutUI, relativeTo: nil, bookmarkDataIsStale: &isStale)    

然后使用 directoryURL 来访问文件夹,并写入文件,这个过程也需要在 startAccessingSecurityScopedResource 和 stopAccessingSecurityScopedResource 之间进行:

let isAccessing = directoryURL?.startAccessingSecurityScopedResource() ?? false
if !isAccessing {
    // 无法访问文件夹
    return
}

let fileURL = directoryURL?.appendingPathComponent(fileName)
do {
    try content.write(to: fileURL!, atomically: true, encoding: .utf8)
    directoryURL?.stopAccessingSecurityScopedResource()
    // 写入成功
} catch {
    directoryURL?.stopAccessingSecurityScopedResource()
    // 写入失败
}

注意:在info.plist中应该增加下列配置

<key>NSUbiquitousContainers</key>
<dict>
    <key>iCloud.appBundleId</key>
    <dict>
        <key>NSUbiquitousContainerIsDocumentScopePublic</key>
        <true/>
        <key>NSUbiquitousContainerSupportedFolderLevels</key>
        <string>Any</string>
        <key>NSUbiquitousContainerName</key>
        <string>appName</string>
    </dict>
</dict>

至此,我们已经实现了使用 UIDocumentPickerViewController 获取文件夹路径,并将路径存储为 Bookmark,以便在后续写入文件时无需让用户再次选择的功能。希望对你的开发工作可以带来帮助。

参考文献:
https://developer.apple.com/documentation/uikit/view_controllers/providing_access_to_directories

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容