ios - dispatch_after 在 ios 上循环不工作

标签 ios objective-c delayed-execution

我需要在 for 循环中延迟 1 秒,但它不起作用。我需要用动画延迟 1 秒删除 tableview 单元格,这样它就会一个一个地删除。目前所有行都在同时删除。For 循环已经在dispatch_after 中持续了3 秒,因此它嵌套在dispatch_after 中。在for 循环dispatch_after 之外,它正在工作。

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    for(int i=array_messages.count;i>0;i--)
     {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
            [array_messages removeObjectAtIndex:0];
            NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:indexPath.section];
            [self.tableViewMessage deleteRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationTop];
            });

     }
    });

最佳答案

您的 for 循环将几乎立即遍历整个序列,这意味着您的内部 dispatch_after 调用将全部设置为接近同一时间,因此将在大约同时,这就是您所看到的。

在这种情况下,使用 NSTimer 可能会为您提供更好的服务。像这样:

创建要使用的 NSTimer 属性:

@property (strong) NSTimer* deletionTimer = nil;

将这些方法添加到您的类中:

- (void)startDeletionTimer {
    [self killDeletionTimer];
    self.deletionTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(deletionTimerFired:) userInfo:nil repeats:YES];
}

- (void)killDeletionTimer {
    [self.deletionTimer invalidate];
    self.deletionTimer = nil;
}

- (void)deletionTimerFired:(NSTimer*)timer {
    NSUInteger numberOfRecords = [array_messages count];

    if (!numberOfRecords) {
        // None left, we're done
        [self killDeleteionTimer];
        return;
    }

    [array_messages removeObjectAtIndex:0];
    [self.tableViewMessage deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:indexPath.section]] withRowAnimation:UITableViewRowAnimationTop];
}

用这个启动计时器:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    [self startDeletionTimer];
});

与使用带有延迟的内部 dispatch_after 的选项相比,这有一些优点。它将优雅地处理 array_messages 数组中的更改,因为它的计数是在每次迭代时检查的,而不是在开始时假设的。例如,如果您有 30 条消息,则整个删除过程将需要 30 秒。如果在该时间段内添加了一条新消息,或者更糟的是,一条消息以某种方式被删除,您的应用程序将在最后一个 dispatch_after 触发时崩溃,因为索引和/或行将不存在。同样,如果用户离开 View ,tableView 可能会被释放,然后你就会崩溃。

另一个优点是,如果在这 30 秒内缓慢/痛苦地显示记录被删除时,用户想要继续前进,您可以终止计时器并立即删除所有行。

关于ios - dispatch_after 在 ios 上循环不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37043486/

相关文章:

ios - AS3 - iOS - 可以检测用户的语言设置吗?

iphone - 获取 nsdictionary 中特定键的值

ios - 如何在 Xamarin ios 中获取导航栏后退按钮的大小?

objective-c - 如何全局更改UIKit属性的默认值?

objective-c - 如何使用 Swift 中的 AXUIElementCopyAttributeValue?

javascript - 延迟 javascript 执行直到 DOM 更改完成

javascript - 如何遍历关联数组并在数据 block 之间延迟呈现数据 block

ios - 带单位的数字与 VoiceOver

ios - StoreKit 更改商店通知?

jquery - 定义 jQuery.each() 循环步骤之间的超时