我在iOS上的Objective C中使用反向地理编码返回城市时遇到了麻烦。我能够在completionHandler中记录这个城市,但是如果从另一个函数中调用它,我似乎无法弄清楚如何将它作为字符串返回。
city变量是在头文件中创建的NSString。
- (NSString *)findCityOfLocation:(CLLocation *)location
{
geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
if ([placemarks count])
{
placemark = [placemarks objectAtIndex:0];
city = placemark.locality;
}
}];
return city;
}
答案 0 :(得分:7)
您的设计不正确。
由于您正在执行异步调用,因此无法在方法中同步返回值。
completionHandler
是将来会被称为某个块的块,因此您必须更改代码的结构以在调用块时处理结果。
例如,您可以使用回调:
- (void)findCityOfLocation:(CLLocation *)location {
geocoder = [[CLGeocoder alloc] init];
typeof(self) __weak weakSelf = self; // Don't pass strong references of self inside blocks
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
if (error || placemarks.count == 0) {
[weakSelf didFailFindingPlacemarkWithError:error];
} else {
placemark = [placemarks objectAtIndex:0];
[weakSelf didFindPlacemark:placemark];
}
}];
}
- (void)didFindPlacemark:(CLPlacemark *)placemark {
// do stuff here...
}
- (void)didFailFindingPlacemarkWithError:(NSError *)error {
// handle error here...
}
或块(我通常更喜欢)
- (void)findCityOfLocation:(CLLocation *)location completionHandler:(void (^)(CLPlacemark * placemark))completionHandler failureHandler:(void (^)(NSError *error))failureHandler {
geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
if (failureHandler && (error || placemarks.count == 0)) {
failureHandler(error);
} else {
placemark = [placemarks objectAtIndex:0];
if(completionHandler)
completionHandler(placemark);
}
}];
}
//usage
- (void)foo {
CLLocation * location = // ... whatever
[self findCityOfLocation:location completionHandler:^(CLPlacemark * placemark) {
// do stuff here...
} failureHandler:^(NSError * error) {
// handle error here...
}];
}
答案 1 :(得分:1)
反向地理编码请求异步发生,这意味着findCityOfLocation
方法将在completionHandler处理响应之前返回。我建议您不要依赖于findCityOfLocation
方法返回的城市,而只是在completionHandler中执行您想要的城市行动:
- (void)findCityOfLocation:(CLLocation *)location
{
geocoder = [[CLGeocoder alloc] init];
__weak typeof(self) weakSelf = self;
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
if ([placemarks count])
{
placemark = [placemarks objectAtIndex:0];
weakSelf.city = placemark.locality;
// we have the city, no let's do something with it
[weakSelf doSomethingWithOurNewCity];
}
}];
}