本文的文案由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