如何检测iCloud/OneDrive目录中文件是onDisk还是onDemand状态?
判断iCloud/OneDrive按需文件是否已本地下载
在macOS里,iCloud或OneDrive这类特殊目录下的文件有两种状态:onDisk(本地存储) 和 onDemand(按需获取),Finder中会显示对应的云图标。现有一段Swift代码用于获取这类目录内容,需要判断文件是已经完整下载到本地,还是仅存在文件名占位。
原代码:
func getDirContent(){ let startURL = URL(fileURLWithPath: "/Users/name/Library/Mobile Documents/iCloud~com~bbc~Pic/Documents") do { let enumerator = FileManager.default.enumerator(at: startURL, includingPropertiesForKeys: [ .contentModificationDateKey, .fileSizeKey, .isRegularFileKey], options: [ .skipsHiddenFiles, .skipsPackageDescendants], errorHandler: { (url, error) -> Bool in print("directoryEnumerator error at \(url): ", error) return true } )! print("Level: \(enumerator.level)") for item in enumerator { let fileURL = item as! URL print("URL: >\(fileURL.absoluteString)<") let resourceValues = try fileURL.resourceValues(forKeys: Set([.creationDateKey, .isDirectoryKey, .fileSizeKey, .isRegularFileKey])) if (resourceValues.isRegularFile!) { // is this file on Disk or "on Demand" // if let size = resourceValues.fileSize { // do something .... // } } } } catch { print(error) } }
解决方法
要判断文件状态,核心是通过URL的资源键读取对应状态值,区分iCloud和第三方云服务的文件:
添加状态判断的资源键:
- 针对iCloud文件:使用
isUbiquitousItemDownloadedKey - 针对OneDrive等第三方云文件:使用
isDownloadedKey(macOS 10.15+支持)
- 针对iCloud文件:使用
修改代码实现判断:
把这些资源键加入请求集合,然后通过可选绑定读取状态值,判断文件是否已本地下载。
修改后的代码:
func getDirContent(){ let startURL = URL(fileURLWithPath: "/Users/name/Library/Mobile Documents/iCloud~com~bbc~Pic/Documents") do { // 新增用于判断下载状态的资源键 let resourceKeys: Set<URLResourceKey> = [ .creationDateKey, .isDirectoryKey, .fileSizeKey, .isRegularFileKey, .isUbiquitousItemDownloadedKey, .isDownloadedKey ] let enumerator = FileManager.default.enumerator( at: startURL, includingPropertiesForKeys: Array(resourceKeys), options: [.skipsHiddenFiles, .skipsPackageDescendants], errorHandler: { (url, error) -> Bool in print("directoryEnumerator error at \(url): ", error) return true } )! print("Level: \(enumerator.level)") for item in enumerator { guard let fileURL = item as? URL else { continue } print("URL: >\(fileURL.absoluteString)<") let resourceValues = try fileURL.resourceValues(forKeys: resourceKeys) guard let isRegularFile = resourceValues.isRegularFile, isRegularFile else { continue } // 检查iCloud文件状态 if let isICloudDownloaded = resourceValues.isUbiquitousItemDownloaded { print("\(fileURL.lastPathComponent): \(isICloudDownloaded ? "已本地下载" : "仅按需存在")") } // 检查第三方云(如OneDrive)文件状态 if let isThirdPartyDownloaded = resourceValues.isDownloaded { print("\(fileURL.lastPathComponent): \(isThirdPartyDownloaded ? "已本地下载" : "仅按需存在")") } } } catch { print(error) } }
补充说明
isUbiquitousItemDownloadedKey是iCloud专属的判断键,返回true意味着文件已完整下载到本地,false则是仅显示文件名的占位文件。isDownloadedKey是通用型键,适配大多数第三方云服务的按需文件,同样true代表本地已存储,false代表仅占位。- 非云按需文件对应的状态值会是
nil,所以用可选绑定来安全读取,避免崩溃。
内容的提问来源于stack exchange,提问作者mica
相关产品推荐
相关产品推荐

