Yin& Yang初始化 - 在调用init之前等待碎片

时间:2018-05-31 20:24:16

标签: ios objective-c grand-central-dispatch

假设您有一个方法可以在两个单独的块中返回信息,如下所示:

@interface SomeObject : NSObject
- (instancetype)initWithA:(NSString *)aInfo bInfo:(NSString *)bInfo;
@end

- (void)someMethod:(void (^)(NSString *aInfo))firstBlock
       secondBlock:(void (^)(NSString *bInfo))secondBlock {
  firstBlock(@"a"); secondBlock(@"b");
}
- (void)ourMethod:(void (^)(SomeObject *object))completionBlock {
  SomeObject *someObject = [[SomeObject alloc] initWithA:aInfo bInfo:bInfo];
  [self someMethod:^(NSString *aInfo) {
    //
  } secondBlock:^(NSString *bInfo) {
    //
  }];
  completionBlock(someObject);
}

如果两个块都已完成,您将如何初始化someObject并将其传回?

假设两个块都是异步执行的。

我试图摆弄GCD的派遣小组来解决这个问题,然而,这似乎并不是最佳的。

2 个答案:

答案 0 :(得分:3)

由于您需要使用从someObject调用中使用的两个块中获取的值创建someMethod,因此您需要在调用两个块后创建someObject。 / p>

- (void)ourMethod:(void (^)(BOOL initializationComplete))completionBlock {
    __block NSString *a = nil;
    __block NSString *b = nil;

    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    dispatch_group_enter(group);

    [self someMethod:^(NSString *aInfo) {
        a = aInfo;
        dispatch_group_leave(group);
    } secondBlock:^(NSString *bInfo) {
        b = bInfo;
        dispatch_group_leave(group);
    }];

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        SomeObject *someObject = [[SomeObject alloc] initWithA:a bInfo:b];
        completionBlock(someObject);
    });
}

这不会阻止ourMethod的调用者,并且只有在两个块完成后才会确保完成块。

此解决方案假设两个块是异步运行的。

答案 1 :(得分:1)

你可以使用信号量,但是 - 通常 - 使异步操作同步是一个红色标记,表示设计不良。

这两个块本身是异步的吗?如果是这样,您可以__block BOOL firstDone = NO;__block BOOL secondDone = NO;并进行相应检查以确定是否该调用completionBlock。仍然很难看,你在那里想要一个同步原语,以确保你没有参加比赛,但这样做有效。

如果firstBlock()secondBlock()同步且在同一个队列中,则只需在第二个完成后调用completionBlock()

或者,如果它们是异步的并且同时进行了调度,则在异步队列上抛出“em”,然后在调用completionBlock的队列上抛出一个屏障块。