gpt4 book ai didi

iOS block 设计 : Nested Blocks With Return Values?

转载 作者:行者123 更新时间:2023-12-01 18:54:50 24 4
gpt4 key购买 nike

我有一个委托(delegate)回调方法,需要将数据(例如 NSArray )返回给调用者。

我可以从另一个 block 调用中获取这些数据。谁能帮我设计一个在这种情况下使用 block 的设计。

我想出了类似的东西,但不确定这是否是正确的方法。

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
};

无法使用 return的原因在 A 行和 B 行(请参阅代码中的注释)是您返回 onSuccess: block 函数和 onError: block 函数而不是 eventsForDate: .

然而,一个重要的提示:上面的设计只有在你的 getEventsForDate: 的情况下才有效。不 dispatch (或者它总是在 eventsForData block 的同一个线程中运行。

编辑:

如上所述,如果您有 dispatch,这将不会总是按预期工作。在您的 getEventsForDate: .因为你不能保证 C 行会在 A 行和 B 行之后执行。这真的归结为 getEventsForDate:作品。这是另一个更好地说明问题的示例。没有 sleep(1)在代码的底部,您可能会得到 resultnil ;与 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:被分派(dispatch)到后台线程,这意味着它非常慢并且希望在后台执行。并用信号量或任何东西阻塞你的主线程会破坏一切。所以更好的方法仍然是在 block 中做任何你想做的事情并删除 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.
}];
};

关于iOS block 设计 : Nested Blocks With Return Values?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28266218/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com