dispatch_after无法在ios

时间:2016-05-05 06:01:35

标签: ios objective-c delayed-execution

我需要1秒延迟for循环,但它无法正常工作。我需要使用动画删除1秒延迟的tableview单元格,以便逐个删除。目前所有行都在同时删除。对于循环已经在dispatch_after中3秒,所以它嵌套在dispatch_after.Out端,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];
            });

     }
    });

5 个答案:

答案 0 :(得分:1)

你不能把延迟放在' for循环'。如果你想延迟循环使用NSTimer。

答案 1 :(得分:1)

您的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触发时,您的应用将会崩溃,因为索引和/或行不会存在。同样,如果用户导航远离视图,则可以取消分配tableView,然后您将崩溃。

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

答案 2 :(得分:0)

使用以下代码延迟代码执行

double delayInSeconds = 1.0;
dispatch_time_t disTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(disTime, dispatch_get_main_queue(), ^(void){
    //place your code
});

如果您有任何问题,请告诉我。

答案 3 :(得分:0)

尝试这个我实际上没有尝试过,所以不确定

for(int i=array_messages.count;i>0;i--)
                    {

                        int delay = (array_messages.count - i) + 1;
                        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * 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];
                        });

                    }

答案 4 :(得分:-1)

@ DJTiwari尝试这是它的工作

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread
    dispatch_async(dispatch_get_main_queue(), ^(void){
        for(int i=array_messages.count;i>0;i--)
        {
            [NSThread sleepForTimeInterval:1];
            [array_messages removeObjectAtIndex:0];
            NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:indexPath.section];
            [self.tableViewMessage deleteRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationTop];
        }
    });
});