objective-c - NSOperationQueue 位于 NSOperation 内部

标签 objective-c cocoa-touch afnetworking nsoperation nsoperationqueue

我创建了一个 NSOperation ,其目标是从 20 个 URL 下载一些图像(例如 20 个)。 因此,在这个 NSOperation 中,我创建了 20 个 AFImageRequestOperation,将它们添加到 NSOperationQueue 中,并在队列上调用 -waitUntilAllOperationsAreFinished

问题是,它不会等待,它会立即返回。这是代码

- (void)main {
    NSArray *array = [I have the 20 links stored in this array];

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

    for (int i = 0; i < array.count; i++) {                
        NSURL *url = [NSURL URLWithString:[array objectAtIndex:i]];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        AFImageRequestOperation *op = [AFImageRequestOperation imageRequestOperationWithRequest:request imageProcessingBlock:^UIImage *(UIImage *image) {
            return image;
        } success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
        // SUCCESS BLOCK (not relevant)
        } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
        // FAILURE BLOCK (not relevant)
        }];

        [self.queue addOperation:op];
    }

    [self.queue waitUntilAllOperationsAreFinished]; // Here is the problem it doesn't wait
    DDLogWarn(@"-- %@ FINISHED --", self);

}

在控制台中,DDLogWarn(@"-- %@ FINISHED --", self); 在每个操作开始之前打印,所以我的猜测是 waitUntilAllOperationsAreFinished code> 没有完成它的工作,也没有等待,但是 20 个操作在那之后仍在运行,这可能意味着 main 还没有返回,所以我不知道该怎么办再想一想。

编辑1:实际上我想知道,成功和失败中的DDLog是否因为waitUntilAllOperationsAreFinished阻塞线程,直到所有操作完成。这也许可以解释为什么我看不到任何事情正在发生,而且一切都是突然发生的。

最佳答案

出于与您类似的原因,我发现创建一个包含其他 NSOperationsNSOperation 很有用,即我有很多较小的任务组成了一个较大的任务我想将更大的任务视为一个单元,并在完成时收到通知。我还需要序列化较大任务的运行,因此一次只能运行一个任务,但是当每个大任务运行时,它可以在其内部执行多个并发操作。

在我看来,像你一样,创建一个 NSOperation 来管理大任务是一个好方法,而且我没有在文档中读过任何说不要这样做的内容。

看起来您的代码可能仍然可以工作,因此您可以继续使用 NSOperation。

根据您的情况,阻塞线程可能是合理的。如果阻塞不合理,但您想继续使用 NSOperation,则需要创建一个“并发”NSOperation,请参阅 Concurrency Programming Guide: Configuring Operations for Concurrent Execution

如果您一次只允许下载一张图像,则可以使用 @jackslashs 建议来表示操作结束,或者如果您想允许并发图像下载,则可以使用单个 NSBlockOperation 作为最后一个操作,并使用 -[NSOperation addDependency:] 使其依赖于所有其他操作,以便它最后运行。

当您收到一切都已完成的信号时,您可以按照文档中的描述适当设置​​ isFinishedisExecuting 标志来完成您的主要 NSOperation.

诚然,这有一定程度的复杂性,但您可能会发现它很有用,因为一旦这种复杂性隐藏在 NSOperation 中,外部的代码可能会更简单,就像我的情况一样。

如果您决定创建并发 NSOperation,您可能会发现 Apple 示例代码 LinkedImageFetcher : QRunLoopOperation 作为起点非常有用。

关于objective-c - NSOperationQueue 位于 NSOperation 内部,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14832956/

相关文章:

ios - 确定 iPhone 是否真正连接到互联网或仅在受限热点之后

ios - NSUserDefaults 或 NSCache - 存储数据的最佳方式

ios - 使用核心数据中的日期获取记录

ios - 在 Array of Dictionaries of array 中搜索一个值

objective-c - 避免复制 NSMutableArray 以使用多线程写入进行读取

ios - AFNetworking 3 AFMultipartFormData 获取字节数据作为响应

ios - 为什么在 AFNetworking 中使用点对点类型(NSProgress * __autoreleasing *)而不仅仅是点类型(NSProgress * __autoreleasing)?

ios - 在后台线程加载 UITableView 图像

objective-c - predicateWithBlock : used for? 中 block 的绑定(bind)参数是什么

ios - AFNetworking (AFHttpClient) 离线模式不适用于 NSURLRequestReturnCacheDataDontLoad 策略