xcode 处理块、完成处理程序、dispatch_async 与 dispatch_sync

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9510225/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 23:29:21  来源:igfitidea点击:

Dealing with Blocks, completion handlers, dispatch_async vs dispatch_sync

iphoneobjective-cxcode

提问by acecapades

I'm executing an online fetch of data in a thread and I want to do something immediately after the block is executed.

我正在线程中执行在线数据获取,并且我想在执行块后立即执行某些操作。

Here's my code:

这是我的代码:

- (IBAction)refresh:(UIBarButtonItem *)sender {
    NSLog(@"checking");
    [self editToolbar];
    dispatch_queue_t fetchQ = dispatch_queue_create("Refreshing", NULL);
    dispatch_async(fetchQ, ^{
        [self setupFetchedResultsController];
        [self fetchImonggoItemsDataIntoDocument: self.itemDatabase];
    });
    dispatch_release(fetchQ); 

    NSLog(@"done checking");
    //do something here
}

The thing is dispatch_async returns immediately and "done checking" prints immediately even before the block is done executing. How do I solve this?

事情是 dispatch_async 立即返回并且“完成检查”甚至在块执行完成之前立即打印。我该如何解决这个问题?

采纳答案by gregheo

I think it's an architectural issue. The tasks are something like:

我认为这是一个架构问题。任务是这样的:

  1. edit toolbar
  2. fetchImonggoItemsDataIntoDocument
  3. do something else
  1. 编辑工具栏
  2. fetchImonggoItemsDataIntoDocument
  3. 做别的事

If these must be done exactly in order then I don't quite understand the use of blocks or queues; just run the statements after each other and you'll be set.

如果这些必须完全按顺序完成,那么我不太了解块或队列的使用;只需依次运行语句即可。

Otherwise, alternative #1 would be to use dispatch_syncrather than dispatch_async. Again, I'm not quite sure what the benefit of using a queue would be but there it is.

否则,替代 #1 将使用dispatch_sync而不是dispatch_async. 同样,我不太确定使用队列的好处是什么,但它确实存在。

Alternative #2 would be to use a callback from the block. Something like:

替代方法 #2 是使用块中的回调。就像是:

- (IBAction)refresh:(UIBarButtonItem *)sender {
    NSLog(@"checking");
    [self editToolbar];
    dispatch_queue_t fetchQ = dispatch_queue_create("Refreshing", NULL);
    dispatch_async(fetchQ, ^{
        [self setupFetchedResultsController];
        [self fetchImonggoItemsDataIntoDocument: self.itemDatabase];
        [self doneChecking]; // <-- NOTE! call the callback
    });
    dispatch_release(fetchQ); 
}

// NOTE! refresh: has been split up into two methods
- (void)doneChecking:
    NSLog(@"done checking");
    //do something here
}

回答by nacho4d

As others have already suggested, this is probably what you need.

正如其他人已经建议的那样,这可能是您所需要的。

NSArray *items = [iMonggoFetcher fetchImonggoData:IMONGGO_GENERIC_URL_FOR_PRODUCTS withFormat:@"json" withDateRangeArgs:args];
[document.managedObjectContext performBlock:^{
    for (NSDictionary *itemInfo in items){
        [Product productWithImonggoInfo:itemInfo inManagedObjectContext:document.managedObjectContext];
    }
    // Put here what you need :)
}];