简体   繁体   English

iOS Objective-C 等待异步进程

[英]iOS Objective-C wait for async process

I am calling the code below from within the AppDelegate:我正在从 AppDelegate 中调用以下代码:

-(void) application:(UIApplication *)application performFetchWithCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler {


-(BOOL)backgroundRefresh{
    newData = false;
    callStartTime = [NSDate date];

    [self processAll];
       dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        while(!fetchComplete);
        NSLog(@"NOW COMPLETE");

   });
    NSLog(@"Got here now!");
    return newData;
}

The call to [self processAll] runs code that has async calls etc, and will keep looping around until all activities are complete, repeatedly calling itself.对 [self processAll] 的调用运行具有异步调用等的代码,并将继续循环直到所有活动完成,重复调用自身。 Once all tasks are complete, fetchComplete is set to true.完成所有任务后,fetchComplete 将设置为 true。 This part works fine.这部分工作正常。

I need the code to wait for fetchComplete to be true, and then return a bool back to AppDelegate.我需要代码等待 fetchComplete 为真,然后将布尔值返回给 AppDelegate。

The issue is, that quite rightly, the current checking, whilst it works to show the NSLogs etc., is of no use to returning the BOOL back to the caller, as the process is currently async.问题是,非常正确的是,当前检查虽然可以显示 NSLogs 等,但对于将 BOOL 返回给调用者毫无用处,因为该进程当前是异步的。 I have set it to async so that it runs, otherwise, I find that the processAll code is being blocked from running.我已经将它设置为 async 以便它运行,否则,我发现 processAll 代码被阻止运行。

Could someone please shed some light onto how I can monitor for fetchComplete, and only once that is true return the bool to the calling function?有人可以解释一下我如何监视 fetchComplete,并且只有在这种情况下才将 bool 返回给调用函数吗?

I have tried moving the return to into the async block, after the while has returned, but this returns a syntax error due to calling within the block.在 while 返回后,我尝试将 return 移动到异步块中,但是由于在块内调用,这会返回语法错误。

Use a notification.使用通知。 First, you must start listening to the notification like this首先,您必须像这样开始收听通知

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(fetchDidComplete)
                                             name:@"fetchDidComplete"
                                           object:nil];

Where ever you set fetchComplete to true, post a notification like this无论何时将 fetchComplete 设置为 true,请发布这样的通知

[[NSNotificationCenter defaultCenter] postNotificationName:@"fetchDidComplete"
                                                    object:self
                                                  userInfo:nil];

Then you should have a method called fetchDidComplete that will do the post completion work.然后你应该有一个名为 fetchDidComplete 的方法来完成后完成工作。 Don't forget to stop listening to the notification once done.完成后不要忘记停止收听通知。

[[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:@"fetchDidComplete"
                                              object:nil];

You don't wait for an async process to finish.您无需等待异步进程完成。 That makes it synchronous.这使它同步。 You need to change your thinking.你需要改变你的想法。

There are a number of different ways to handle async APIs.有多种不同的方式来处理异步 API。

  1. Pass in a completion block传入一个完成块
  2. Assign a delegate and define a method that gets called on completion.分配一个委托并定义一个在完成时调用的方法。
  3. Send a notification when the process completes.进程完成时发送通知。

There are no doubt more, but the whole idea of an async API is that it returns immediately, and you DON'T wait for it to finish.毫无疑问,异步 API 的整个想法是它立即返回,而不是等待它完成。 As the other person said, never, ever, use code like while(!fetchComplete) .正如另一个人所说,永远不要使用像while(!fetchComplete)这样的代码。 That is a seriously bad idea.这是一个非常糟糕的主意。

The manor of which you are trying to solve this problem is a bit atypical.你试图解决这个问题的庄园有点不典型。

Generally this is done with either delegation, blocks or notifications .通常这是通过委托、 blocksnotifications

The idea being you only want to perform some function after the completion of some asynchronous method .这个想法是你只想在完成一些异步方法后执行一些function

Let's say we have an asyc processor called AyncProcessor .假设我们有一个名为AyncProcessor的异步处理器。

AyncProcessor * processor = [AyncProcessor sharedProcessor];
processor.delegate = self;
[processor start];

is a fairly common way to do the delegation.是一种相当常见的方式来做委托。 The assumption here is that there is a protocol defined with a callback method that is run upon completion.这里的假设是有一个协议定义了一个回调方法,该方法在完成时运行。

//protocol method
-(void) processingComplete;

// and at some point in AsyncProcessor
[self.delegate processingComplete] 

more info on delegation here关于代表团的更多信息在这里

Blocks can be used as well块也可以使用

AyncProcessor * processor = [AyncProcessor sharedProcessor];
[processor start:^()/{
  ///code in this block will complete after processing has completed
 }];

more info on blocks can be found here可以在此处找到有关块的更多信息

And as already shown you can send a NSNotification .正如已经显示的那样,您可以发送NSNotification

For your problem delegation is likely a good idea.对于您的问题,委托可能是一个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM