NSOperationOperationQueue cancelAllOperations方法不会停止操作

时间:2017-10-13 10:42:12

标签: ios cocoa nsurlsession nsoperationqueue

如何取消NSOperationQueue中的所有操作?我使用了cancelAllOperations方法,但它没有用,NSOperationQueue仍在调用服务器来上传照片。

我把NSOperationQueue上的每一个连接都用循环。

- (void)sendingImage:(NSArray *)imgArray compression:(CGFloat)compression
{    
    hud = [MBProgressHUD showHUDAddedTo: self.view animated: YES];
    hud.label.text = [NSString stringWithFormat: @"Waiting for Loading"];
    [hud.button setTitle: @"Cancel" forState: UIControlStateNormal];
    [hud.button addTarget: self action: @selector(cancelWork:) forControlEvents: UIControlEventTouchUpInside];

    __block int photoFinished = 0;

    self.queue = [[NSOperationQueue alloc] init];
    self.queue.maxConcurrentOperationCount = 5;
    [self.queue addObserver: self forKeyPath: @"operations" options: 0 context: NULL];

    NSBlockOperation *operation = [[NSBlockOperation alloc] init];
    __weak NSBlockOperation *weakOperation = operation;    
    __block NSString *response = @"";

    for (int i = 0; i < imgArray.count; i++) {

        operation = [NSBlockOperation blockOperationWithBlock:^{
            [self uploadingPhoto];
        }];

        [operation setCompletionBlock:^{
            NSLog(@"Operation 1-%d Completed", i);
            photoFinished++;

            dispatch_async(dispatch_get_main_queue(), ^{
                hud.label.text = [NSString stringWithFormat: @"%d photo complete uploading", photoFinished];
            });
        }];

        [self.queue addOperation: operation];
    }
}

我想按MBProgressHUD上的取消按钮首先取消所有NSURLSessionDataTask,然后取消所有操作,但没有工作。

- (void)cancelWork:(id)sender {
    NSLog(@"cancelWork");    
    NSLog(@"self.queue.operationCount: %lu", (unsigned long)self.queue.operationCount);

    [session getTasksWithCompletionHandler:^(NSArray<NSURLSessionDataTask *> * _Nonnull dataTasks, NSArray<NSURLSessionUploadTask *> * _Nonnull uploadTasks, NSArray<NSURLSessionDownloadTask *> * _Nonnull downloadTasks) {

        if (!dataTasks || !dataTasks.count) {
            return;
        }
        for (NSURLSessionDataTask *task in dataTasks) {
            [task cancel];

            if ([self.queue operationCount] > 0) {
                [self.queue cancelAllOperations];
            }
        }
    }];
}

我使用信号量让NSURLSession成为同步连接。

- (void)uploadingPhoto {

    request setting above

    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    config.timeoutIntervalForRequest = 1200;

    session = [NSURLSession sessionWithConfiguration: config];

    dataTask = [session dataTaskWithRequest: request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        if (error == nil) {
            str = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
            NSLog(@"str: %@", str);
        }

        dispatch_semaphore_signal(semaphore);
    }];
    NSLog(@"task resume");
    [dataTask resume];

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    return str;
}

非常感谢任何评论或解决方案。

1 个答案:

答案 0 :(得分:1)

NSOperation默认情况下不支持取消。请参阅课程文档。一个提取物是:

  

取消操作不会立即强制它停止正在进行的操作。虽然期望所有操作都遵守已取消属性中的值,但您的代码必须明确检查此属性中的值并根据需要中止。

使用NSBlockOperation实现取消似乎也很难。