ios - 如何使用 NSOperationQueue 和 NSOperation 在后台 Thread 使用 NSTimer 定期调用序列化下载任务

标签 ios objective-c nstimer nsoperation nsoperationqueue

我想为每个方法使用 NSOperation 执行一些网络方法,并将操作添加到在后台线程上设置的 NSOperationQueue,我希望 NSOperations 发生序列化。

创建 NSOperation 队列的调用会定期调用,每 30 秒使用 NSTimer。

这是到目前为止截取的代码:

NSTimer *timer;
NSOperationQueue *bgQueue;

- (void)startdDownloadLoop{

    if (![self.timer isValid]){

        self.bgQueue = [[NSOperationQueue alloc] init];
        self.timer = [NSTimer scheduledTimerWithTimeInterval:30.0
                                                      target:self
                                                    selector:@selector(updateDB)
                                                    userInfo:nil
                                                     repeats:YES];

    }

}

- (void)updateDB{

    //        Next code was removed since si similar to the call `[self.bgQueue cancelAllOperations];`, as @robinkunde suggested
    //        for (NSOperation *operation in [self.bgQueue operations]) {
    //            if (operation.isExecuting) {
    //                [operation cancel];
    //            }
    //        }

    [self.bgQueue cancelAllOperations];


    self.bgQueue = [[NSOperationQueue alloc] init];
    self.bgQueue.maxConcurrentOperationCount = 1;

    NSBlockOperation *blockOp1 = [NSBlockOperation blockOperationWithBlock:^{
        [NetworkManager downloadCars];
    }];

    NSBlockOperation *blockOp2 = [NSBlockOperation blockOperationWithBlock:^{
        [NetworkManager downloadPartsForAllCars];
    }];

    NSBlockOperation *blockOp3 = [NSBlockOperation blockOperationWithBlock:^{
        [NetworkManager downloadEachPathSpecs];
    }];

    [self.bgQueue addOperation:blockOp1];
    [self.bgQueue addOperation:blockOp2];
    [self.bgQueue addOperation:blockOp3];

}

NetworkManager 方法是带有完成处理程序的 POST/GET 方法,在完成下载后,它们将日期保存在数据库中,然后使用通知更新 UI。

更新:

由于困惑,我想将我关于代码的实际问题作为休假发布:

1- 如果 NSOperationQueue 的执行是串行的?

2 - 如果当我调用[operation cancel] 时会停止操作的执行?

3 - 如果当我调用 cancelAllOperations 并重新初始化它是清除当前 NSOperationQueue 的正确方法吗?

最佳答案

1) 您可以将队列上的属性maxConcurrentOperationCount设置为1,以确保串行执行。

2) 这只对操作设置了 isCancelled 属性。需要对此更改采取行动并将其自身移动到完成状态,以便可以将其从队列中删除。

至于您的具体示例:NSBlockOperation 在所有附加 block 都已返回时被视为已完成。这实际上意味着,除非对 NetworkManager 的调用是同步的,否则该 block 会立即返回,操作被视为已完成,并且队列将开始下一个操作。队列完全有可能在第一个网络操作完成之前完成。如果您想一次执行一个,这不是执行此操作的方法。

您可以使用同步网络操作,但仍然不允许您取消它们。

查看此答案:NSURLSession with NSBlockOperation and queues

3) 这与 2) 有关。 cancelAllOperations 所做的只是对所有操作设置 isCancelled 属性。在这些操作完成之前,队列将继续存在。在同一属性上创建新队列不会改变这一点。

关于ios - 如何使用 NSOperationQueue 和 NSOperation 在后台 Thread 使用 NSTimer 定期调用序列化下载任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37967509/

相关文章:

objective-c - 如何手动改变 body 的特征?

iphone - didSelectRowAtIndexPath 与部分

ios - 将 NSTimer 的 fireDate 之前的时间加倍

arrays - Swift 中的 NSTimer 将标签设为数组值

ios - 在 UIImageView 上调整图像,如 FB 封面照片

xcode - NSTimer:浮点值无法转换为 UInt8,因为它大于 UInt8.max

ios - 更改 UITableView 中的 UIButton 图像 UIButton 单击

c# - PickerView 工具栏的完成按钮不起作用

iOS 在向 Web 服务请求时加载进度条

iphone - quartz 阴影无法正确绘制