函数从块返回值

时间:2011-11-04 14:46:05

标签: iphone objective-c ipad

如果我有一个返回int的函数并且从块中获取int的返回值怎么办?

例如:

- (int) queryForKey:(NSString *)aKey view:(UIButton *)aView countView:(UIView *)aCountView counter:(int) count {
    //some initialization
    [query countObjectsInBackgroundWithBlock:^(int number, NSError * error) {
        [aCountView addSubview:self.generateCountLabel];

        if (number > 0){
            [aView setUserInteractionEnabled:YES];
            [aView setEnabled:YES];
        }
        //return number; //doing this will generate an error
    }];
}

另一个问题是,如果我将一个int作为上述函数的参数传入,我想为它分配一个值。有些事情甚至可能吗?

3 个答案:

答案 0 :(得分:1)

你的块没有返回值,它返回void。

要返回一个值,您可以在块和存储区外的变量上使用__block修饰符,然后在那里回答,然后可以使用其余方法(或代码)。

答案 1 :(得分:1)

问题是你有一个同步方法(想要立即返回值的方法),需要返回一个从异步方法派生的值(一个在不同的线程中进行业务的方法)。

有几种方法可以解决这个问题:

  • 等待countObjectsInBackgroundWithBlock:方法完成,使用__block模式作为@simonpie描述。

  • return number;替换为对结果编号感兴趣的某个地方。这也意味着queryForKey:view:countView:可能会返回void

后者是首选解决方案,因为它不会阻止调用queryForKey:...方法的线程。

请注意,您不能在除主线程之外的任何东西上执行UIKit类。如果该块在后台线程上执行,那么在块中执行的操作无效。

答案 2 :(得分:-1)

我找到了更好的解决方案。希望这可以帮助那些偶然发现问题的人。我会像你这样实现你的代码的解决方案:

- (int) queryForKey:(NSString *)aKey view:(UIButton *)aView countView:(UIView *)aCountView counter:(int) count {
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    __block int number;

    //some initialization
    [query countObjectsInBackgroundWithBlock:^(int number, NSError * error) {
        dispatch_async(queue, ^{
            [aCountView addSubview:self.generateCountLabel];

            if (number > 0){
                [aView setUserInteractionEnabled:YES];
                [aView setEnabled:YES];
            }
            dispatch_semaphore_signal(sema);
        });
    }];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    return number; //doing this will no longer generate an error
}

然后用另一个dispatch_async封装你的调用,这样你的信号量等待调用就不会阻塞主线程。

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
    [self queryForKey:@"AKey" view:myView countView:myCountView counter:aCounter];
});