Ios Objective-C返回嵌套块中声明的对象的方法
在以下代码块中,第一个方法调用第二个方法,该方法应返回地理编码过程的结果:Ios Objective-C返回嵌套块中声明的对象的方法,ios,objective-c,oop,objective-c-blocks,Ios,Objective C,Oop,Objective C Blocks,在以下代码块中,第一个方法调用第二个方法,该方法应返回地理编码过程的结果: - (void)foo { CLPlacemark *currentMark = [self reverseGeocodeLocation:locationManager.location]; } - (CLPlacemark *)reverseGeocodeLocation:(CLLocation *)location { CLGeocoder *geocoder = [[CLGeocoder all
- (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
中的所有代码嵌套在geocoder的完成块中,这很快就会变得非常难看,并且很难维护
将
foo
中的currentMark
变量设置为第二个方法的完成块的结果而不将其嵌套在块中的最佳方法是什么?只需添加回调块以返回值,而不必让函数返回值
试试这个:
- (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);
}];
}
然后富就会
- (void)foo {
__block CLPlacemark *currentMark;
[self reverseGeocodeLocation:(CLLocation *)location withCallback:(CLPlacemark *mark, NSError *error) {
currentMark = mark;
}];
}
似乎处理这个问题的最佳方法是使用代理。这样,程序流就不会因为等待完成块返回的不确定时间量而受阻 下面是一个简短的例子,说明我的决定:
- (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表示)不会受到任何阻碍,查询数据的视图控制器基本上可以“通知”数据已加载,而不是直接要求返回值。是的,这种情况正好相反。您仍然会得到一个完成块,然后您必须将所有附加代码分层,以确保
foo
中的currentMark
不是零。当前标记是从块中的地理编码器返回的,因此您没有真正的选择。为什么这是一个问题?如果你遵守你写的方法论(或者我目前的方法论),当你在前面的完成块中提出额外的请求时,你最终会得到一大堆括号。只是不太优雅,哈哈。对很多丑陋的牙套。异步编程很难。但是我们不知道是谁在呼叫foo,因此假设调用方不需要阻止。现在,您将开始链接控制器和视图,而不是代理。