Obj-C同步使用块回调的异步方法

时间:2014-10-08 19:01:22

标签: objective-c asynchronous objective-c-blocks synchronous

我有一个名为getCount:的异步方法,该方法转到网址,计算一些内容,并在完成后调用一个回调。

我有另一个同步的方法,需要获取这些结果,将它们放入消息中,然后返回该消息。以下是两者:

- (NSString *)describe {
    __block bool gotCount = NO;
    [self getCount:^(int count) {
        NSLog(@"Got the count: %i", count);
        _count = count;  // _count is an ivar of the object with this method.
        gotCount = YES;
    }];
    // Pause here until the count has been fetched.
    while (!gotCount) {
        [NSThread sleepForTimeInterval:0.05];
    }
    return [NSString stringWithFormat:@"The count is %i", _count];
}

当我尝试这个时,我的回调永远不会被调用。它从不打印

Got the count 0

或此方案中的任何其他值。

如果我注释掉while循环,则会打印出该消息。所以我知道getCount:方法有效,我的循环等待它到达时出现了问题。

我需要getCount:保持异步(在其他更重要的地方使用它)我需要describe保持同步。我怎么处理这个?

2 个答案:

答案 0 :(得分:2)

一个可能的事情:如果你的describe方法在主线程中,那么你也从主线程调用getCount方法,所有web回调都在主线程中。 你用线程睡眠阻止主线程 - >你不能从网上回电来计算。

编辑:

尝试从另一个线程调用getCount方法。使用例如

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   [self getCount:^(int count) {
       NSLog(@"Got the count: %i", count);
       _count = count;  // _count is an ivar of the object with this method.
       gotCount = YES;
   }];
});

编辑2:

我尝试了这段代码并且工作正常 - >你的getCount方法中的线程可能有问题。

- (NSString *)describe {
    __block bool gotCount = NO;
    __block NSInteger _count;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [NSThread sleepForTimeInterval:5.00];
        _count = 5;
        gotCount = YES;
    });
    // Pause here until the count has been fetched.
    while (!gotCount) {
        [NSThread sleepForTimeInterval:0.05];
    }
    return [NSString stringWithFormat:@"The count is %li", _count];
}

答案 1 :(得分:0)

一种方法可行但是QUITE the hack(苹果公司一直在mac上使用旧苹果)将在等待时运行runloop:

注意:这依赖于与describe方法

在同一队列上的回调

请参阅:JSON async request [相同问题]


一个自包含的工作示例:

#import <Foundation/Foundation.h>

@interface T : NSObject

- (NSString *)describe;
@end

@implementation T {
    int _count;
}

- (void)getCount:(void (^)(int c)) handler {
    dispatch_async(dispatch_get_global_queue(0,0), ^ {
        sleep(5);
        dispatch_sync(dispatch_get_main_queue(), ^{
            handler(55);
        });
    });
}

- (NSString *)describe {
    __block bool gotCount = NO;
    [self getCount:^(int count) {
        NSLog(@"Got the count: %i", count);
        _count = count;  // _count is an ivar of the object with this method.
        gotCount = YES;
    }];
    // Pause here until the count has been fetched.
    while (!gotCount) {
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
    }
    return [NSString stringWithFormat:@"The count is %i", _count];
}

@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        T *t = [T new];
        NSLog(@"describe: %@", [t describe]);
    }
}