我正在重新审视我去年提出的一个问题。我没有正确地问这个问题,并且相信我没有提供相关的代码。我删除了这个问题并且更好地改写了(这次我很长。这次我希望有人能理解我的问题。也许我一直在屏幕上看太长时间看我的错误或者iOS 10.2已经实现了新的iCloud权限。 我有通用的iOS(和macOS版本)应用程序,可以将文本文件写入和读取到iCloud。将文件写入iCloud不是问题。正在阅读它们让我绕圈子跑来跑去。
(1)如果iPad写出文件,它可以将其读回应用程序,但它无法读取iPhone使用同一个应用程序写出的文件。 (2)如果iPhone写出文件,它可以将其读回应用程序,但它无法读取使用相同应用程序的iPad写出的文件。 (3)Mac可以读取iOS设备写出的文件,但iOS设备无法读取macOS设备写出的文件。
现在,当尝试读取文件时,它会失败并显示错误代码260 - 该文件不存在。对于上述每个上述步骤都会发生这种情况。由于它是相同的通用应用程序,它让我完全惊呆了。设备不会将特定于设备的任何内容添加到文件名中。这意味着我误解了有关在设备上缓存iCloud文件的一些事情。我明白iOS(和macOS)会自动解决这个问题。
以下是我的iOS项目中的代码。
这是我设置metaDataQuery以从iCloud获取文件URL的方法(在iOS项目中):
//Get list of iCloud files or read a file from iCloud
func iCloud_ListOrReadFiles(_ accountName:String)
{
//Format for search predicate of document(s) in iCloud storage
var theFormat :String
//List documents or open a document
if(listMode)
{
requestedAccountName = kSuffix //List all files with suffix kSuffix (= "txt")
theFormat = "%K ENDSWITH %@" //Just like all text documents
} else {
requestedAccountName = accountName //Read the file
theFormat = "%K LIKE %@"
}
//现在设置metaDataQuery metadataQuery = NSMetadataQuery() metadataQuery!.predicate = NSPredicate.init(格式:theFormat,NSMetadataItemFSNameKey,requestedAccountName!)
metadataQuery!.searchScopes = [NSMetadataQueryUbiquitousDocumentsScope]
NotificationCenter.default.addObserver(self,selector:#selector(metadataQueryDidFinishGathering),
name:NSNotification.Name.NSMetadataQueryDidFinishGathering,object:metadataQuery)
metadataQuery!.start()
}
这是我通过metaDataQuery(在iOS项目中)处理从iCloud返回的文件URL的方式:
func metadataQueryDidFinishGathering(_ notification:Notification) { 让query = notification.object!如! NSMetadataQuery
query.disableUpdates() //Disable the querying updates
NotificationCenter.default.removeObserver(self, name:NSNotification.Name.NSMetadataQueryDidFinishGathering, object:query) //And remove from Notifications
query.stop() //Final nail in the coffin for this query
let results = NSArray.init(array: query.results)
let theCount = query.resultCount
//Vamoose if nothing found
if (theCount < 1) {
return
}
if(listMode) //Just create a list of iCloud files found
{
listMode = false
for i in 0..<theCount
{
let account = Accounts()
account.startDate = nil
account.stopDate = nil
account.modDate = nil //Can't set it below because the compiler is chocking up there.
account.location = 2
let urlString = ((results[i] as AnyObject).value(forAttribute: NSMetadataItemURLKey) as! URL).lastPathComponent
account.accountName = String( (urlString as NSString).deletingPathExtension)
listOfAccounts?.add(account)
}
//If user wants the list sorted alphabetiucally, then do it
if(appSettings.bSortingsFlag)
{
if( (((listOfAccounts?.count)!-1)) > onDeviceIndex) { //Sort only iCloud accounts
self.bubbleSortAccountNames(onDeviceIndex, toIndex:((listOfAccounts?.count)!-1))
}
}
} else { //Came here to read one text file
ubiquityURL = ((results[0] as AnyObject).value(forAttribute: NSMetadataItemURLKey) as? URL)! //URL of file
print(String(format:"metadataQueryDidFinishGathering:ubiquityURL = %@", ubiquityURL! as CVarArg)) //Let's see it
copyFromiCloud2Device(ubiquityURL! as NSURL) //Copy the file from iCloud (in the function below)
}
这是我使用metaDataQuery返回的iCloud URL从iCloud读取文件的方式。代码下面是控制台打印(在iOS项目中):
/ * 使用标准NSFilemanager方法copyItemAtURL从iCloud复制文本文件 这里没有使用UIDocument类 * / func copyFromiCloud2Device(_ iCloudURL:NSURL) { 让nameWithSuffix = iCloudURL.lastPathComponent! //仅提取文件名(以及用于目标的后缀) let deviceURL = CPLib()。fullURLPath(nameWithSuffix,inFolder:nil)//我的函数获取设备上Documents文件夹的完整路径
print("copyToDeviceDocumentsFolder:iCloudURL \(iCloudURL)")
print("copyToDeviceDocumentsFolder:deviceURL \(deviceURL)")
do {
try FileManager.default.copyItem(at: iCloudURL as URL, to:deviceURL) //Now copy the file from iCloud
//Process the contents after 0.25 seconds
Timer.scheduledTimer(timeInterval: 0.25, target:self, selector:#selector(converText2CoreData), userInfo:nil,repeats:false)
} catch let error as NSError { // End up here with error (code 260 = The file doesn't exist)
print("copyToDeviceDocumentsFolder:nameWithSuffix = \(nameWithSuffix)")
let noSuffix = String((nameWithSuffix as NSString).deletingPathExtension) //Remove the text suffix because user doesn't need to know that
let title = String(format:"Copy '%@' from iCloud",noSuffix!)
let errorDescription = String(format:"Error (%d), %@",error.code, error.localizedFailureReason!)
CPLib().showAlert(title, message:errorDescription, button:["Done"], calledBy:self, action:nil)
}
}
以下是打印语句:“metadataQueryDidFinishGathering”和“CopyFromiCloud2Device”(在iOS项目中):
metadataQueryDidFinishGathering:ubiquityURL = file:///private/var/mobile/Library/Mobile%20Documents/UZMZA52SXK~com~macsoftware~CheckPad/Documents/DemAccount.txt
copyToDeviceDocumentsFolder:iCloudURL file:///private/var/mobile/Library/Mobile%20Documents/UZMZA52SXK~com~macsoftware~CheckPad/Documents/DemAccount.txt copyToDeviceDocumentsFolder:deviceURL file:///var/mobile/Containers/Data/Application/DF9EE5C0-E3EA-444A-839D-C2E8C1D1B408/Documents/DemAccount.txt copyToDeviceDocumentsFolder:无法读取nameWithSuffix = DemAccount.txt
+++++++++++++ 这是macOS中用于从iCloud(工作)中读取相同文本文件的Objective C代码:
/ * 使用标准NSFilemanager方法copyItemAtURL从iCloud复制文件,而不是setUbiquitous。 没有UIDocument实现这里使用的类 * / - (void)copyFromiCloud:(NSString *)fileName { NSString * nameWithExtension = [fileName stringByAppendingPathExtension:kTEXTOne]; NSURL * deviceURL = [[CoreDataStuff accountsLocation:nil] URLByAppendingPathComponent:nameWithExtension]; NSURL * iCloudURL = [ubiquityContainerURL URLByAppendingPathComponent:nameWithExtension];
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSError *error = nil;
//Copy the file from iCloud to local directory "Documents" on device
BOOL success = [fileManager copyItemAtURL:iCloudURL toURL:deviceURL error:&error];
if (!success)
[self showAnAlert:[NSString stringWithFormat:@"Copy %@ from iCloud",fileName] //Private library call
message:[NSString stringWithFormat:@"Aborting...%@",[error localizedFailureReason]] altButton:nil];
else {
[NSTimer scheduledTimerWithTimeInterval:0.25 //Set up a timer to fire up after .25 seconds
target:self
selector:@selector(convertText2CoreData:) //My function to convert the data to CoreData
userInfo:nil
repeats:NO];
}
}
我还注意到,当iOS设备无法找到该文件时,会出现在Xcode控制台中:
****在iPad或iPhone上运行****
2017-03-25 20:09:15.543784 CheckPad [405:66745] [MC] systemgroup.com.apple.configurationprofiles路径的系统组容器是/private/var/containers/Shared/SystemGroup/systemgroup.com。 apple.configurationprofiles 2017-03-25 20:09:15.554561 CheckPad [405:66745] [MC]从公共有效用户设置中读取。
答案 0 :(得分:0)
阅读Apple iOS概述后,我发现了为什么我的iCloud文件访问失败了。 iOS保留了一个&#39; iCloud容器&#39;设备上的区域。要从iCloud读取,操作系统会查看该文件的本地存储区域(也称为ubiquity容器)。如果它没有找到它,它将返回错误代码260 - 该文件不存在。如果文件之前已保存到iCloud,则只能从本地存储中读取。如果该文件已被其他设备修改(更晚的日期),则会从iCloud下载该版本。 要解决这个问题,我只需使用
&#34; FileManager.default.startDownloadingUbiquitousItem(at:iCloudURL)&#34;
使用&#34; metadataQueryDidFinishGathering&#34;返回的URL 然后延迟2秒:
DispatchQueue.main.asyncAfter(截止日期:.now()+。秒(1),执行:{ 代码在这里下载文件 }
然后下载该文件。到目前为止,这一直在发挥作用。