我有一个委托回调方法,需要将数据(例如NSArray
)返回给调用者。
我可以从另一个块调用中获取此数据。在这种情况下,任何人都可以请帮助我进行设计以使用块。
我想出了类似的方法,但不确定这是否是正确的方法。
NSArray* (^eventsForDate)(NSDate *) = ^(NSDate *date) {
[[DataManager sharedInstance] getEventsForDate:date onSuccess:^(NSArray *events) {
return events; //Obviously this doesn't work. Need help here.
} onError:^(NSError *error) {
return @[];
}];
};
//Delegate call back
- (NSArray *) calendarEventsForDate:(NSDate *) date
{
return eventsForDate(date);
}
最佳答案
因此,您正在寻找的或多或少如下。
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
};
之所以不能在A行和B行使用
return
(请参阅代码中的注释)的原因是,您将返回onSuccess:
块函数和onError:
块函数,而不是eventsForDate:
。但是,请注意:上述设计仅在
getEventsForDate:
不是dispatch
的情况下才有效(或者它始终在eventsForData
块的同一线程中运行)。编辑:
如上所述,如果您的
dispatch
中有getEventsForDate:
,则此方法将无法始终按预期工作。因为您不能保证C行将在A行和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);
}
因此,您真正要做的是阻止C行,并等待至少执行A行或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:
调度到后台线程,则意味着它非常慢,并且希望在后台执行。并用semephore阻塞主线程或其他任何东西都会破坏一切。因此,更好的方法仍然是在块中执行您想做的任何事情,并永久删除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.
}];
};