假设您有一个方法可以在两个单独的块中返回信息,如下所示:
@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的派遣小组来解决这个问题,然而,这似乎并不是最佳的。
答案 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
的队列上抛出一个屏障块。