2

在以下代码块中,第一个方法调用第二个方法,该方法应返回地理编码过程的结果:

- (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将变量 infoo设置为第二种方法的完成块的结果而不将其嵌套在块中的最佳方法是什么?

4

2 回答 2

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;
            }];
 }
于 2013-08-09T16:53:22.683 回答
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 呈现)不受任何阻碍,查询数据的视图控制器本质上可以“通知”数据已加载,而不是直接要求返回值。

于 2013-08-12T18:03:29.697 回答