Ios Objective-C在主线程上运行而不阻塞它的方法

Ios Objective-C在主线程上运行而不阻塞它的方法,ios,objective-c,multithreading,grand-central-dispatch,Ios,Objective C,Multithreading,Grand Central Dispatch,我知道这听起来不对!但我需要实现的是在主线程上运行一个巨大的枚举,这显然会阻塞整个应用程序。我要寻找的是循环周期之间的动画或延迟,这样其他代码就有机会执行。 这是我的密码: for (NSTextCheckingResult* match in matchedArray) { dispatch_async(dispatch_get_main_queue(), ^{ [self addAttributes:@{NSBackgroundColorAttributeName:[

我知道这听起来不对!但我需要实现的是在主线程上运行一个巨大的枚举,这显然会阻塞整个应用程序。我要寻找的是循环周期之间的动画或延迟,这样其他代码就有机会执行。 这是我的密码:

for (NSTextCheckingResult* match in matchedArray) {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self addAttributes:@{NSBackgroundColorAttributeName:[UIColor redColor]} range:match.range];
    });
}
正如注释中提到的,此代码与UI相关,必须在主线程上运行


我也尝试过在之后调度,但它似乎会阻止线程的等待时间。到底是我能做到这一点,还是我必须重新设计我的整个逻辑

与其他评论者一样,我也对“应该在主线程上运行”的主张持怀疑态度,但我会让你相信,你比我更了解自己的情况

您可以编写庞大的枚举,将中间状态存储在某种变量或结构中,让它运行X次迭代,然后使用完成处理程序放置延迟调用[self-performSelector:@selectorcrazyEnumerationMethod:withObject:nil afterDelay:2.0]:

当所有数据处理到您满意的程度时,您必须设计某种标志来翻转,以防止该方法再次触发

基本上,您将在数据集上迭代多次,每次迭代都会暂停操作,直到最后处理完所有数据,并翻转标志以防止再次迭代


根据您的大量枚举所需要的内容,这可能是一个非常复杂的编写过程,但您永远不知道,也许有一种干净而聪明的方法来存储中间状态,并在每次迭代中选择停止的位置。

当您在主线程上运行时,匹配数组中的每个元素都会按顺序处理。因此,您可以通过向数组的处理元素n分配一个块来实现您希望与主队列上的其他任务的交织,该数组在完成任务后向处理元素n+1分配一个块

与直接输入答案的所有代码大致相同的内容:

- (void) processIndex:(NSUInteger)index ofArray:(NSArray *)matchedArray
{
   NSTextCheckingResult *match = matchedArray[index++];
   [self addAttributes:@{NSBackgroundColorAttributeName:[UIColor redColor]}
                 range:match.range];
   if(index < matchedArray.count)
      dispatch_async(dispatch_get_main_queue(),
                     ^{ [self processIndex:index ofArray:matchedArray]; });
}


...

if (matchedArray.count > 0)
   dispatch_async(dispatch_get_main_queue(),
                  ^{ [self processIndex:0 ofArray:matchedArray]; });

HTH

它与UI相关,我使用的是TextKit,这个方法应该在主线程上运行,没有其他方法可以不在另一个线程上执行枚举,然后在需要更新UI时在主线程上调用它?或者你列举的每个对象都是需要更新的UI元素吗?@BenAvery是的,这就是我能做的!addAttribute方法是它需要在主线程上的位置。对象只是存储属性需要应用到的范围。TextKit将负责REST,值得注意的是,如果在枚举完成之前不处理中断,这会使您容易受到各种错误和崩溃的攻击。老实说,我仍然看不出你的方法和我的方法有什么不同!但很明显,你的方法非常有效,这正是我想要的。今天我还学了一个新单词交错!非常感谢!上述方法通过在前一个任务执行之前不添加任务来降低任务添加到队列的速度,for循环一次添加所有任务。这为执行其他内容提供了更多的机会。如果这仍然不够,您可以从dispatch\u async切换到dispatch\u after,以在任务之间增加额外的延迟,从而为其他工作留出更多的运行时间。