我正在尝试从坐标中找到用户的位置以保存到我的数据库中。
要查找我正在使用 reverseGeocode 的位置名称。但是因为它是一个块方法,我的self.locationName将返回(并保存为nil)到数据库中。所以我试图找到问题的解决方案,并尝试将以下解决方案放在一起使用信号量尝试阻止,直到我得到一个我可以保存的locationName,但应用程序只是在按下保存按钮时挂起。我是否应该以这种方式解决这个问题,还是有更好的方法?
dispatch_semaphore_t semaphore;
- (void)reverseGeocode:(CLLocation *)location {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(@"Finding address");
if (error) {
NSLog(@"Error %@", error.description);
} else {
CLPlacemark *placemark = [placemarks lastObject];
self.locationName = [NSString stringWithFormat:@"%@", ABCreateStringWithAddressDictionary(placemark.addressDictionary, NO)];
dispatch_semaphore_signal(semaphore);
}
}];
}
-(NSString *)findLocation:(CLLocation *)startingLocation
{
semaphore = dispatch_semaphore_create(0);
[self reverseGeocode:startingLocation];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //should maybe timeout
return self.locationName;
}
答案 0 :(得分:3)
你正在考虑这一切都错了。这不是异步代码的工作原理。在代码返回之前, NOT 阻止。只需启动代码即可启动反向地理编码,然后完成。现在,当反向地理编码完成时,它会回叫您,您可以使用返回的信息执行任何操作。这是完成处理程序的重点:它在反向地理编码完成之前不会运行。
摆脱信号量,让事情异步发生。这是一个没有辅助方法的完整示例:
CLLocation* loc = userLocation.location;
[geo reverseGeocodeLocation:loc
completionHandler:^(NSArray *placemarks, NSError *error)
{
if (placemarks) {
CLPlacemark* p = [placemarks objectAtIndex:0];
NSLog(@"%@", p.addressDictionary); // do something with address
}
}];
正如您已经被告知的那样,如果您真的想从另一个方法调用它然后再做一些事情,那么将一个块传递给此方法并在完成处理程序内调用该块。这意味着您传递的块是在地理编码完成后运行的代码,这正是您想要的 - 没有信号量而且没有冻结应用程序。
冻结应用程序是不好的形式,如果你长时间执行它,WatchDog会杀死你的应用程序死机。只是不要这样做。