【问题标题】:How can I detect that iCloud has finished downloading the document, as well as run the completion handler?如何检测 iCloud 已完成下载文档并运行完成处理程序?
【发布时间】:2012-01-30 05:39:57
【问题描述】:

从 iCloud 加载文档时,必须调用

openWithCompletionHandler:^(BOOL success)completionHandler

此函数将启动一个后台线程,从 iCloud 下载文件,并在完成加载后运行完成处理程序。

在此过程中,此调用之后的任何代码都会继续运行。

在下载完成之前,如何阻止程序继续运行?

在调用从云端加载后,我的代码立即尝试使用该文档 - 但当然,由于它没有完成下载,代码会崩溃。

详情如下:

我目前正在开发一个保存文件库来处理文件的保存/加载、加密、压缩和 iCloud 支持。用户调用我的库函数 LoadFileAtPath 并且有一个参数指定他们是否希望我检查 iCloud 中的这个特定文件。

当函数启动并且我要检查 iCloud 时,我做的第一件事就是调用我的 iCloudload 函数,如下所示:

bool cloudLoad = [iCloudStorageManager readFileFromiCloud:filePath name:fileName];

在这个函数中,我调用 openWithCompletionHandler,如下所示:

if ([fileManager fileExistsAtPath:[docURL path]]) 
        {
            [doc openWithCompletionHandler:^(BOOL success){
                if (!success) 
                {
                    // Handle the error.
                    NSLog(@"Failed to retrieve document:%@ from iCloud URL:%@.", fileName, [docURL absoluteString]);
                }
                else
                {
                    NSLog(@"Replacing document in sandbox with iCloud version");
                    BOOL* dir = nil;
                    if (![fileManager fileExistsAtPath:filePath  isDirectory:dir])
                    {
                        NSError *fileError = nil;
                        if(![fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:&fileError])
                        {
                            NSLog(@"Error creating file directory: %@\n%@\n%@\n%@", [fileError localizedDescription], [fileError localizedFailureReason], [fileError localizedRecoveryOptions], [fileError localizedRecoverySuggestion]);
                        }

                    }
                    // save new data if success
                    [iCloudStorage replaceDocumentInSandboxWith:doc newData:doc.loadedContents];
                }
            }];
            [doc release];
        }

之后,我的代码继续尝试提取数据,并对其进行各种操作,例如解密、解压缩并将文件数据交给调用者。

我当前的(hacky)解决方案是在最初调用 readFileFromiCloud 之后,有一个检查布尔值的循环,如下所示:

while (!cloudDidFinishLoad) 
{
     sleep(10);
}

这个布尔值被初始化为假,并且在上面看到的“replaceDocumentInSandboxWith”函数中,布尔值被设置为真。

但是,我发现这会导致程序挂起,它永远不会完成加载 iCloud 文件,并且永远不会调用完成处理程序。

我不知道该怎么做。我需要程序停止运行代码,直到下载完成,但我不知道该怎么做。

【问题讨论】:

    标签: ios icloud


    【解决方案1】:

    不确定您是否找到了答案,但我会为您的库创建一个协议,然后设置一个委托,您可以在完成处理程序完成时调用该委托。

    然后可以在您的主控制器中设置为委托,一旦文件准备好,您就可以从库中接收文件已准备好使用的调用。所以伪代码会是这样的......

    1. 创建 iCloudStorageManager
    2. 将自己设置为 iCloudStorageManager 的委托
    3. 在 iCloudStorageManager 上调用打开的文件
    4. 在这里做你需要做的任何事情,设置活动指示器或锁定界面,或者两者都不做,只是假设它工作,除非代理告诉你它没有。基本上在这里,您的块将结束,当调用委托函数时,您的主控制器将恢复对界面的控制。

    5. 在委托函数中,您将从 iCloudStorageManager 收到有关它是否成功的状态。一旦你接到来自 iCloudStorageManager 的电话,你就可以释放界面,发布一个事情进展顺利或事情进展不顺的警报,并提供回复......无论你想做什么。

    但这就是我处理它的方式。 (是的,这是一个老问题,但我觉得我有一些见识:))

    【讨论】:

    • 我不再从事这个项目,因为我的老板在查看了我的基本情况后决定选择其他人。但如果我还在做这个,这就是我会做的。当时我不知道代表是如何工作的。感谢您的有用回复:)
    【解决方案2】:

    在等待文件完成下载时冻结用户界面(通过主线程上的睡眠调用)对我来说似乎真的很苛刻,我希望您的客户不会喜欢这样。

    为什么不抛出一个活动微调器,例如:

    然后在调用 iCloud 完成处理程序时将其带走?当活动视图显示在屏幕上时,您可以通过 UIView 的 userInteractionEnabled 属性(设置为 FALSE)禁用其余的 UI 交互。

    【讨论】:

    • 虽然这是个好主意,但我的 lib 无法直接控制界面,它只是一组其他应用程序将调用的函数。理想情况下,他们会在单独的线程中调用我的加载函数。
    • 如果您的库最终“拥有”正在保存和加载的文档(并用于提供对该文档的访问),如果尚未加载,则返回错误或一些 NO 布尔值。调用应用程序没有理由崩溃。
    • 这是一种可能,但是这对调用者意味着什么?他们如何区分“错误返回,文件由于某种原因加载失败”或“错误返回,iCloud 尚未完成加载,请稍后重试以获取您的数据”?我会为 NSError 对象包含一个附加参数并让他们在失败时检查吗?很公平 - 这是一种可能性,但它仍然会产生一个问题,即有人需要让程序等待直到完成,并且显然只是睡眠阻止了 completionHandler 被调用。
    • Welp...根据我的经验,我给了你我最好的答案。我没有太多信息可以继续(直到我发布我的答案后才意识到你只是作为一个图书馆这样做)。由于应用程序将依赖于您的库,因此您应该设置一些关于如何以及何时可以访问文档的条件(是的,一定要返回一个 NSError 参数来告诉调用者可能出了什么问题)。这将是一个公共图书馆还是只是一个内部使用的图书馆?如果仅用于内部应用程序,请务必获取主视图的句柄并设置“加载”活动指示器。
    • 谢谢,我正在与我的上级讨论解决方案 - 这可能是我们达成的解决方案。感谢您的意见!
    猜你喜欢
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-02
    • 2014-01-08
    • 2015-09-10
    • 1970-01-01
    相关资源
    最近更新 更多