【问题标题】:iOS device unable to access an iCloud account created by another iOS deviceiOS 设备无法访问由其他 iOS 设备创建的 iCloud 帐户
【发布时间】:2017-08-20 15:17:56
【问题描述】:

我正在重新审视我去年在这里提出的一个问题。我没有正确地提出问题,并认为我没有提供相关代码。我删除了那个问题,并改写了更好的措辞(这次是长篇大论。这次我希望有人能理解我的问题。也许我在屏幕上看了太久才看到我的错误,或者 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(在 iOS 项目中)获取文件 URL 的方式:

//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 元数据查询 = NSMetadataQuery() metadataQuery!.predicate = NSPredicate.init(format: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) { 让查询 = 通知对象!作为! 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 而不是 setUbiquitous 从 iCloud 复制文件。 此处没有使用 UIDocument 实现类 */ -(void)copyFromiCloud:(NSString *)fileName { NSString *nameWithExtension = [文件名 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] 从公共有效用户设置中读取。

【问题讨论】:

    标签: ios macos icloud


    【解决方案1】:

    阅读 Apple iOS 概述后,我发现了我的 iCloud 文件访问失败的原因。 iOS 在设备上保留了一个“iCloud 容器”区域。要从 iCloud 中读取,操作系统会查看该文件的本地存储区域(也称为 ubiquity 容器)。如果它没有找到它,它会返回错误代码 260 - 该文件不存在。如果一个文件之前已经保存到 iCloud,它只是从本地存储中读取它。如果文件已被另一台设备修改(以后的日期),它会从 iCloud 下载该版本。 为了解决这个问题,我简单地使用了

    "FileManager.default.startDownloadingUbiquitousItem(at: iCloudURL)"

    使用“metadataQueryDidFinishGathering”返回的 URL 然后将其延迟 2 秒:

    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1),执行:{ 在此处下载文件的代码 }

    然后下载文件。到目前为止,这一直有效。

    【讨论】:

      猜你喜欢
      • 2017-09-25
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多