如何返回在delay_after块内确定的值? [英] How do I return a value determined within a delay_after block?

查看:134
本文介绍了如何返回在delay_after块内确定的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Objective-C的新手,很费时间弄清楚如何完成以下工作.我来自javascript背景,因此我可能无法以正确的方式进行处理.

Very new to Objective-C and having a rough time figuring out how to accomplish the following. I come from a javascript background, so I may not be approaching this in the correct way.

在我的视图控制器中,我正在调用类方法getLuminosity.我想在7秒钟内从相机中收集一些float,对其求平均值,然后返回该平均值,但不知道如何进行.这是我的getLuminosity代码:

In my view controller I'm making a call to a class method getLuminosity. I want to collect some float's from the camera for 7 seconds, average them, and then return that average but have no clue how to do it. Here is my getLuminosity code:

- (CGFloat) getLuminosity {

    ...

    [vidCam startCameraCapture];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(7 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [vidCam stopCameraCapture];
        NSNumber *averageLumin = [_arrayOfLumins valueForKeyPath:@"@avg.self"];
        return [averageLumin floatValue];
    });

    return floatFromDispatchBlock;

}

感谢您的帮助!

推荐答案

您的方法getLuminosity调用异步方法. 不可避免的使调用方法也异步!

Your method getLuminosity invokes an asynchronous method. This inevitable makes the calling method asynchronous as well!

因此,一种可行方法的第一步是要认识到您的方法getLuminosity异步,异步方法应该提供一种向呼叫站点发信号通知底层异步任务的方法完成:

So, the first step to a working approach is to realize that your method getLuminosity is asynchronous, and an asynchronous method SHOULD provide a means to signal the call-site that the underlying asynchronous task is complete:

我们可能会使用补全处理程序"来完成此操作,但请记住,这不是实现此操作的唯一方法(请参阅@ b52回答如何使用promises完成此操作).

We might use a "completion handler" to accomplish this, but keep in mind that this is not the only way to achieve this (see @b52 answer how to accomplish this with promises).

完成处理程序(更准确地说是一个Block)需要由调用站点定义(即实现).当呼叫站点启动"异步任务时(通过调用异步方法),完成处理程序将传递给异步任务.任务的责任是在完成处理程序时调用"完成处理程序.

The completion handler - a Block to be more precise - needs to be defined (that is, implemented) by the call-site. When the call-site "starts" the asynchronous task (through invoking the asynchronous method) the completion handler gets passed through to the asynchronous task. The task's responsibility is to "call" the completion handler when it is finished.

通常,完成处理程序具有将用于传输异步任务结果的参数.例如,我们可以如下定义一个完成块:

Usually, the completion handler has parameters which will be used to transfer the result of the asynchronous task. For example, we could define a completion block as follows:

typedef void (^completion_t)(NSNumber* averageLumin, NSError* error);

注意:通常,完成处理程序的类型"将由基础异步任务及其要求定义.但是,该块的实现将由呼叫站点提供.

Note: usually, the "type" of the completion handler will be defined by the underlying asynchronous task, respectively its requirements. The implementation of the block, though, will be provided by the call-site.

您的异步方法将如下所示:

Your asynchronous method can then look like this:

- (void) luminosityWithCompletion:(completion_t)completion;

并且可以实现:

- (void) luminosityWithCompletion:(completion_t)completion 
{
    ...

    [vidCam startCameraCapture];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(7 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [vidCam stopCameraCapture];
    NSNumber *averageLumin = [_arrayOfLumins valueForKeyPath:@"@avg.self"];

    if (completion) {
        completion(averageLumin, nil)
    }
});

在呼叫站点上,当结果最终可用时,您可以使用继续"来执行所需的任何操作:

On the call-site, you use a "continuation" to do whatever is necessary when the result is eventually available:

- (void) foo
{        
    ...
    // Define the "continuation" with providing the completion block:
    // Put *everything* that shall be executed *after* the  result is
    // available into the completion handler:
    [self luminosityWithCompletion:^(NSNumber* result, NSError*error) {
        if (error) {
            // handle error
        }
        else {
            // continue on the main thread:
            dispatch_async(dispatch_get_main_queue(), ^{
                // using "result" on the main thread
                float lum = [result floatValue];
                ...


            });
        }             
    }];

}

这篇关于如何返回在delay_after块内确定的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆