我正在试图找出导致以下行为的特殊属性NSRunLoop。
首先,我要做的是等待CLGeocoder在继续之前完成执行。如果我使用完成块,代码将如下所示:
if (/* loc has valid coordinates */)
[gc reverseGeocodeLocation:loc completionHandler:^(NSArray *placemarks, NSError error){
//do things
[gc reverseGeocodeLocation:newloc completionHandler:^(NSArray *placemarks, NSError error){
//do more things with newloc
// MOVE TO NEXT VIEW
}
}
else if (/*still have to check for newloc*/)
[gc reverseGeocodeLocation:loc completionHandler:^(NSArray *placemarks, NSError error){
//do things
//MOVE TO NEXT VIEW
不幸的是,这些块的//do things
部分是冗长的,如果我在自己的函数中嵌套CLGeocoder,它会更清晰,并且在我调用它两次后移动到下一个视图。
我找到了一种迫使等待的方法,感谢答案:Waiting for CLGeocoder to finish on concurrent enumeration
所以新方法有效,但我不知道为什么它有效。这是代码:
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[gc reverseGeocodeLocation:loc completionHandler:^(NSArray *placemarks, NSError *error){
//do things
dispatch_group_leave(group);
}
//this is the confusing part!
while(dispatch_group_wait(group,DISPATCH_TIME_NOW)){
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:1.0f]];
}
dispatch_release(group);
奇怪的是,如果我在没有while循环的情况下执行以下操作,应用程序会挂起:
dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
鉴于我到目前为止所读到的一切,这应该有用,对吗?
更令人困惑的是,NSRunLoop在while循环中是必需的。如果我完全删除它,留下一个空的while循环,循环将无休止地重复。像这样:
//this is the confusing part!
while(dispatch_group_wait(group,DISPATCH_TIME_NOW)){
//without NSRunLoop, this just goes on forever
}
NSRunLoop做了什么让while循环成功结束?
答案 0 :(得分:2)
CLGeocoder
文档说它在主线程上运行完成处理程序块。我推断你正在主线程上运行你的等待或你的while(dispatch_group_wait(...))
循环。如果阻塞主线程,则主线程无法运行完成块。
通过在while循环中调用runMode:beforeDate:
,您可以为运行循环提供运行完成块的机会。
你在做什么很糟糕。你不应该阻止主线程,你应该尽量避免递归地运行一个运行循环(因为,正如你所发现的,它是令人困惑的)。 CLGeocoder
允许您提供完成块的原因是您可以将其设置为然后返回主运行循环。稍后,当CLGeocoder
运行完成块时,您可以以任何您需要的方式使用结果。