Ios 尹及;Yang初始化-在调用init之前等待片段
假设您有一个在两个单独的块中返回信息的方法,如下所示:Ios 尹及;Yang初始化-在调用init之前等待片段,ios,objective-c,grand-central-dispatch,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
@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的调度组来解决这个问题,但是,它似乎不是最优的。您可以使用信号量,但是——一般来说——使异步操作同步是一个危险信号,表明设计不好 这两个块本身是否异步?如果是这样的话,您可以使用
\uu block BOOL firstDone=NO代码>和\u块BOOL secondDone=否
并进行适当的检查,以查看是否是调用completionBlock的时候了。仍然很难看,你需要一个同步原语来确保你不会参加比赛,但这是可行的
如果firstBlock()
和secondBlock()
是同步的并且在同一队列上,那么在第二个队列完成后只需调用completionBlock()
或者,如果它们是异步且同时调度的,则将它们扔到异步队列上,然后在队列上扔一个障碍块来调用completionBlock
您可以使用信号量,但一般来说,使异步操作同步是一个红色标志,表明设计不好
这两个块本身是异步的吗?如果是这样的话,您可以使用\uu block BOOL firstDone=NO代码>和\u块BOOL secondDone=否
并进行适当的检查,以查看是否是调用completionBlock的时候了。仍然很难看,你需要一个同步原语来确保你不会参加比赛,但这是可行的
如果firstBlock()
和secondBlock()
是同步的并且在同一队列上,那么在第二个队列完成后只需调用completionBlock()
或者,如果它们是异步且同时调度的,则将它们放到异步队列上,然后在调用完成块的队列上抛出障碍块,因为您需要使用从调用someMethod
中使用的两个块中获得的值创建someObject
,调用两个块后,需要创建someObject
- (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
的调用者,并且它确保只有在两个块都完成后才调用完成块
此解决方案假定这两个块是异步运行的。由于需要使用从调用someMethod
中使用的两个块中获得的值来创建someObject
,因此需要在调用这两个块后创建someObject
- (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
的调用者,并且它确保只有在两个块都完成后才调用完成块
此解决方案假定两个块异步运行。我喜欢屏障块的想法。。。我试试看。\uu block BOOL
在我看来太难看了。谢谢:)@bbum供参考-这个问题刚刚得到了一个严重的更新,可能会影响你的答案。我喜欢屏障块的想法。。。我试试看。\uu block BOOL
在我看来太难看了。谢谢:)@bbum仅供参考-这个问题刚刚得到了一个严重的更新,可能会影响你的答案。这与我处理的问题类似。。这个模式的主要问题是从aInfo
和bInfo
初始化someObject
。不仅仅是调用completionBlock(YES)代码>:)代码[[NSObject alloc]initWithA:andB:]
甚至无效,但这似乎与您关于在两个块都完成后调用完成块的问题无关。请更新您的问题,并清楚地解释什么是someObject
,什么是initWithA:andB
方法,这两个参数应该是什么,以及它与调用someMethod
的关系。这是有效的。。。如果firstBlock
包含多个变量,所有这些变量都需要传递给SomeObject
,您会有什么不同?您是否会在范围之外添加更多的\u block
变量?有什么更好的主意?要支持从firstBlock
或secondBlock
返回的任意数量的变量@这是一个全新的问题。现在就按照这个答案中的模式来做。如果你认为有一种更好的方法来处理一组特定的工作代码,请考虑发布一个类似于我所处理的代码审查。这个模式的主要问题是从aInfo
和bInfo
初始化someObject
。不仅仅是调用completionBlock(YES)代码>:)代码[[NSObject alloc]initWithA:andB:]
甚至无效,但这似乎与您关于在两个块都完成后调用完成块的问题无关。请更新您的问题,并清楚地解释什么是someObject
,什么是initWithA:andB
方法,这两个参数应该是什么,以及它与调用someMethod
的关系。这是有效的。。。如果firstBlock
包含多个变量,所有这些变量都需要传递给SomeObject
,您会有什么不同?您是否会在范围之外添加更多的\u block
变量?有什么更好的主意?要支持从firstBlock
或secondBlock
返回的任意数量的变量@这是一个全新的问题。现在请按照这个答案中的模式进行操作。如果您以后认为可能有更好的方法来处理特定的一组工作代码,请考虑发布代码审查。