gpt4 book ai didi

ios - 在 objective-c 中延迟或完成循环

转载 作者:行者123 更新时间:2023-11-29 13:05:52 25 4
gpt4 key购买 nike

我有一个应用程序,我需要循环访问并加载存储的数据以生成信息以保存到 PDF 文件、页面。我创建了一个循环,但可以这么说,它运行得太快了。保存的页面加载速度不够快,因此生成的数据不完整。我想我需要创建一个带有延迟或完成处理程序的 for 循环。像这样的东西:

for (int i = 0, i < numberOfPages, doTaskWithCompletion:i++) {
arrayOfPages = [self loadDataAtIndex:i withCompletionHandler:handler];
[self writeDataToFile:arrayOfPages];
}

甚至不确定如何编写该伪代码,但基本上我只想在完成处理程序为加载数据的任务触发后跳转到下一个迭代。

注:源数据来自核心数据,保存为PDF文件。数据是页面和页面的 View 。每个页面可以有 1 次或无限次浏览。每个 View 也可能有数据,比如图像。当前发生的情况是写入的页数是正确的,但是呈现为 PDF 的页面 View 是相同的,因为它们都读取相同的数据,因为在写入 PDF 之前页面没有加载。

最佳答案

您可以按如下方式解决问题:

首先定义一个通用的完成 block 类型。注意,param result 可以是任何东西。如果它是一个 NSError 这表示失败,否则表示成功。

typedef void (^completion_t)(id result);

为您的异步任务定义 block 类型。您的任务将索引作为输入,并且 - 因为它是异步的,所以它需要一个完成 block 作为最后一个参数:

typedef void (^unary_async_t)(int index, completion_t completion);

您的任务 block 对象可以定义如下:

unary_async_t task = ^(int index, completion_t completion) {
[self loadDataAtIndex:index withCompletion:^(id result){
if (![result isKindOfClass:[NSError class]]) {
[self writeDataToFile:result];
result = @"OK";
}
if (completion) {
completion(result);
}
}];
};

注意:您的 loadDataAtIndex:withCompletion: 是异步的,因此,它需要一个完成 block 作为最后一个参数。完成 block 的参数 result 是异步任务的结果,即“页面数组”——如果失败则为 NSError 对象。

在此完成 block 中,您将结果(页面)保存到磁盘,调用 writeDataToFile:。 (我们假设这不会失败)。如果全部完成,task 调用提供的完成 block completion(如果不是 nil)传递整个操作的结果,如果成功则为 @"OK", 以及失败时的 NSError

现在,更有趣的部分是:如何在循环中进行此操作,其中许多_task_s 将按顺序执行,一个接一个:

我们定义了两个辅助方法或函数:

我们最终需要的是一个带有这个签名的函数:

void apply_each_with_range(int lowerBound, int upperBound, 
unary_async_t task, completion_t completion);

这是调用 task N 次的函数,将 index 参数传递给 lowerBound(包括)到 upperBound(不包括),其中 N 等于 upperBound - lowerBound 并且 index 以 < em>下界。

它是一个异步函数,因此将完成 block 作为最后一个参数。我会重复自己吗?嗯,你应该认得模式! ;)

实现如下:

void apply_each_with_range(int lowerBound, int upperBound, 
unary_async_t task, completion_t completion)
{
do_apply(lowerBound, upperBound, task, completion);
}

还有另一个助手 - 它最终执行某种“for_each index in range[upperBound, lowerBound] 顺序调用任务带有参数索引”:

static void do_apply(int index, int upperBound, 
unary_async_t task, completion_t completion)
{
if (index >= upperBound) {
if (completion)
completion(@"OK");
return;
}
task(index, ^(id result) {
if (![result isKindOfClass:[NSError class]]) {
do_apply(index + 1, upperBound, task, completion);
}
else {
// error occurred: stop iterating and signal error
if (completion) {
completion(result);
}
}
});
}

do_apply 函数首先检查索引是否超出范围。如果,则它完成并使用 @"OK"调用完成处理程序。否则,它会使用参数 index 调用 task 并提供一个完成处理程序,该处理程序在 task 完成时被调用,它本身传递任务的结果。如果成功,do_apply 将调用自身并将参数索引递增 1。这可能看起来像一个“递归”——但它不是。 do_apply 在调用自身时已经返回。

如果 task 返回错误,do_apply 停止,在其完成处理程序中“返回”来自 task 的错误(最终由调用站点)。

现在,您只需将这些部分放在您的项目中 - 这应该相当容易。

关于ios - 在 objective-c 中延迟或完成循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18668870/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com