使用reverseGeocodeLocation设置地址字符串:并从方法返回

Wes*_*ley 1 cocoa-touch objective-c ios clgeocoder completionhandler

我尝试将起点和终点本地化为地址字符串,以便我可以将其存储到NSUserDefaults.问题是该方法继续执行并且不设置我的变量.

NSLog(@"Begin");

__block NSString *returnAddress = @"";

[self.geoCoder reverseGeocodeLocation:self.locManager.location completionHandler:^(NSArray *placemarks, NSError *error) {
    if(error){
        NSLog(@"%@", [error localizedDescription]);
    }

    CLPlacemark *placemark = [placemarks lastObject];

    startAddressString = [NSString stringWithFormat:@"%@ %@\n%@ %@\n%@\n%@",
                          placemark.subThoroughfare, placemark.thoroughfare,
                          placemark.postalCode, placemark.locality,
                          placemark.administrativeArea,
                          placemark.country];
    returnAddress = startAddressString;

    //[self.view setUserInteractionEnabled:YES];
}];
NSLog(returnAddress);

NSLog(@"Einde");
Run Code Online (Sandbox Code Playgroud)

这是我的应用程序调试器显示的内容:

启动
einde

例如,我的位置地址是:"Mainstreet 32​​,CITY".然后我想看到的是以下内容:

启动
Mainstreet 32​​,CITY
Einde

问题是我的代码不等待我CLGeocoder完成,所以我的变量returnAddress在返回时没有设置,并且它是空的.

有谁知道如何解决这个问题?

Bio*_*Bio 5

因为reverseGeocodeLocation有一个完成块,它会在执行到达时传递给另一个线程 - 但是主线程上的执行仍将继续进行下一个操作,即NSLog(returnAddress).此时,returnAddress尚未设置因为reverseGeocodeLocationJUST已交给其他线程.

使用完成块时,您必须开始考虑异步工作.

考虑将离开reverseGeocodeLocation作为方法中的最后一个操作,然后使用完成块内的其余逻辑调用新方法.这将确保在您有值之前逻辑不会执行returnAddress.

- (void)someMethodYouCall 
{
    NSLog(@"Begin");
    __block NSString *returnAddress = @"";

    [self.geoCoder reverseGeocodeLocation:self.locManager.location completionHandler:^(NSArray *placemarks, NSError *error) {
        if(error){
            NSLog(@"%@", [error localizedDescription]);
        }

        CLPlacemark *placemark = [placemarks lastObject];

        startAddressString = [NSString stringWithFormat:@"%@ %@\n%@ %@\n%@\n%@",
                              placemark.subThoroughfare, placemark.thoroughfare,
                              placemark.postalCode, placemark.locality,
                              placemark.administrativeArea,
                              placemark.country];
        returnAddress = startAddressString;

        //[self.view setUserInteractionEnabled:YES];

        NSLog(returnAddress);
        NSLog(@"Einde");

        // call a method to execute the rest of the logic 
        [self remainderOfMethodHereUsingReturnAddress:returnAddress];
    }];
// make sure you don't perform any operations after reverseGeocodeLocation.
// this will ensure that nothing else will be executed in this thread, and that the
// sequence of operations now follows through the completion block.
}

- (void)remainderOfMethodHereUsingReturnAddress:(NSString*)returnAddress {
   // do things with returnAddress.
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用NSNotificationCenter在reverseGeocodeLocation完成后发送通知.您可以在任何其他需要的地方订阅这些通知,并从那里完成逻辑.替换[self remainderOfMethodHereWithReturnAddress:returnAddress];为:

NSDictionary *infoToBeSentInNotification = [NSDictionary dictionaryWithObject:returnAddress forKey:@"returnAddress"];

[[NSNotificationCenter defaultCenter] 
    postNotificationName:@"NameOfNotificationHere" 
    object:self
    userInfo: infoToBeSentInNotification];
    }];
Run Code Online (Sandbox Code Playgroud)

是使用NSNotificationCenter的示例.