在下面的代码块中,第一个方法调用第二个方法,该方法应该返回地理编码过程的结果:
- (void)foo {
CLPlacemark *currentMark = [self reverseGeocodeLocation:locationManager.location];
}
- (CLPlacemark *)reverseGeocodeLocation:(CLLocation *)location {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
__block CLPlacemark *placeMark;
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
if (!error) {
if ([placemarks firstObject])
placeMark = [placemarks firstObject];
}
}];
return placeMark;
}
但是,由于程序的执行,不等待地理编码在继续之前完成(因此完成块),因此在地理编码过程完成之前总是存在未实例化地返回placeMark
变量的危险。并调用完成块。在向Web服务发出HTTP请求时,我遇到了同样的困境,其结果不会在不确定的时间内返回。
到目前为止,我看到的唯一解决方案是将foo
中的所有代码嵌套在地理编码器的完成块中,这很快变得非常丑陋且难以维护。
将currentMark
中的foo
变量设置为第二个方法完成块的结果而不将其嵌套在块中的最佳方法是什么?
答案 0 :(得分:0)
不要让函数返回值,只需添加一个回调块来返回值。
试试这个:
- (void)reverseGeocodeLocation:(CLLocation *)location withCallback:(void(^)(CLPlacemark *resultPlacemark, NSError *error))_block {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
_block([placemark objectAtIndex:0], error);
}];
}
然后foo将是
- (void)foo {
__block CLPlacemark *currentMark;
[self reverseGeocodeLocation:(CLLocation *)location withCallback:(CLPlacemark *mark, NSError *error) {
currentMark = mark;
}];
}
答案 1 :(得分:0)
似乎整体处理此问题的最佳方法是使用委托。这样,等待完成块返回的时间不确定,就不会妨碍程序的流程。
以下是我决定的简短例子:
- (void)reverseGeocodeLocation:(CLLocation *)location {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
if (!error) {
if ([placemarks firstObject])
[delegate performSelectorOnMainThread:@selector(done:) withObject:[placemarks firstObject];
}
}];
return placeMark;
}
事后看来,这实际上看起来相当优雅。主线程的控制流程(即UI表示)不受任何阻碍,查询数据的视图控制器基本上可以“通知”数据已加载,而不是直接要求返回值。