因此,您正在寻找的或多或少是以下内容。
NSArray* (^eventsForDate)(NSDate *) = ^NSArray*(NSDate *date) {
__block NSArray *result = nil;
[[DataManager sharedInstance] getEventsForDate:date onSuccess:^(NSArray *events) {
result = events; // Line A
} onError:^(NSError *error) {
result = @[]; // Line B
}];
return result; // Line C
};
您不能在 Line A 和 Line B 使用 return 的原因(请参考代码中的 cmets)是因为您返回的是 @987654324 @块函数和onError:块函数而不是eventsForDate:。
但是,一个重要的注意事项:上面的设计只有在你的getEventsForDate: 没有dispatch 时才有效(或者它总是在eventsForData 块的同一个线程中运行。
编辑:
如上所述,如果您的getEventsForDate: 中有dispatch,这将不会总是按预期工作。因为您不能保证 Line C 将在 Line A 和 Line B 之后执行。这真的归结为getEventsForDate: 的工作原理。这是另一个更好地说明问题的示例。如果代码底部没有sleep(1),您可能将result 设为nil;使用sleep(1),您将可能获得@[@"A"]。
- (void)getEventsForDate:(NSDate *)date
onSuccess:(void(^)(NSArray *))sucessBlock
onError:(void(^)(NSError *))errorBlock
{
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(q, ^{
sucessBlock(@[@"A"]);
});
// sleep(1);
}
所以你真正需要做的是阻止Line C 并等待至少Line A 或Line B 被执行。详情请参考这个问题:
How do I wait for an asynchronously dispatched block to finish?
简而言之,您可以编写如下内容:
NSArray* (^eventsForDate)(NSDate *) = ^NSArray*(NSDate *date) {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
__block NSArray *result = nil;
[[DataManager sharedInstance] getEventsForDate:date onSuccess:^(NSArray *events) {
result = events;
dispatch_semaphore_signal(sema);
} onError:^(NSError *error) {
result = @[@"B"];
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return result;
};
编辑 2
但是,即使是上面的代码也可能对您有用。这听起来不是一个好主意。那是因为,如果getEventsForDate: 被分派到后台线程,这意味着它非常慢并且希望在后台执行。并用信号量或任何东西阻塞你的主线程会破坏一切。所以更好的方法仍然是在块中做任何你想做的事情,并永远删除return。类似于以下内容:
void (^eventsForDate)(NSDate *) = ^void(NSDate *date) {
[[DataManager sharedInstance] getEventsForDate:date onSuccess:^(NSArray *events) {
// Update UI and etc.
} onError:^(NSError *error) {
// Update UI and etc.
}];
};