Objective-C块,变量和CLGeocoder和/或CLPlacemark

Nic*_*ick 0 objective-c-blocks ios5

我是Objective-C的新手,我的C/C++技能非常生疏.有什么更好的时间来学习iOS开发(!)

我正在尝试使用iOS中的CLGeocoder类来反转地理位置.我可以在块/回调中成功获取我感兴趣的数据(街道地址),但是当我尝试使用该数据填充我的变量(块外)时,数据不存在.就好像在MapView对象调用它之前块中的对象消失了.我正在使用__block,据我所知,应该允许变量在块外持久化,但似乎没有.

这是有问题的代码:

- (void) foundLocation:(CLLocation *)loc
{
    CLLocationCoordinate2D coord = [loc coordinate];

    // Get our city and state from a reversegeocode lookup and put them in the subtitle field (nowString).
    // reversegeocode puts that information in a CLPlacemark object

    // First, create the CLGeocoder object that will get us the info
    CLGeocoder *geocoder = [[CLGeocoder alloc]init];

    // Next create a CLPlacemark object that we can store what reverseGeocodeLocation will give us containing the location data
    __block CLPlacemark *placemark = [[CLPlacemark alloc]init];

    __block NSString *sPlacemark = [[NSString alloc]init];

    // This next bit is where things go awry
    [geocoder reverseGeocodeLocation:loc completionHandler:
     ^(NSArray *placemarks, NSError *error) {
         if ([placemarks count] > 0)
         {
             placemark = [placemarks objectAtIndex:0];// this works!! 
             sPlacemark = [placemark thoroughfare]; // as does this! I can see the street address in the variable in the debugger.
         }
     }];

    MapPoint *mp = [[MapPoint alloc] initWithCoordinate:coord
                                                  title:[locationTitleField text] 
                                               subtitle:sPlacemark];

    // add it to the map view
    [worldView addAnnotation:mp];

    // MKMapView retains its annotations, we can release
    [mp release];

    // zoom region to this location
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(coord, 250, 250);

    [worldView setRegion:region
                animated:YES];

    [locationTitleField setText:@""];
    [activityIndicator stopAnimating];
    [locationTitleField setHidden:NO];
    [locationManager stopUpdatingLocation];
}
Run Code Online (Sandbox Code Playgroud)

我还没有完全把头包裹在'块'周围,所以很可能就是问题出在哪里,但是我无法准确地指出是什么.

救命?

提前致谢.

Fir*_*eer 7

所以你所拥有的是一个时间问题.调用reverseGeocodeLocation:completionHandler:异步的.在实际的反向地理定位发生之前,呼叫本身将立即返回.

因此,当调用返回时,您的方法会立即继续,并且您正在创建一个带有尚不存在的地标的注释.

然后在某个时候,您的反向地理定位完成(记住它需要对服务进行网络调用以及所有这些).之后,使用新的传入数据触发您的块.

因此,当您的块实际运行时,您创建的这两个本地__block变量早已消失.为什么?因为那些变量placemarksPlacemark本地(自动)变量,本地方法.它们在方法中存在,然后在方法完成时消失.而且,这种情况发生在您的块甚至可以运行之前.(事实证明这个块会在以后写入每个变量的副本,但这并不重要,因为这个方法已经完成了,你已经尝试过早地阅读它们了.)

如果在此方法的末尾放置一条NSLog消息,并在块中放入另一条消息,您将看到它们触发的顺序.订单将与您可能正在思考的相反.方法结尾处的那个将首先触发,然后是块内的一个.

把它想象成一家餐馆.服务员回到厨房并下订单.现在他不会坐在厨房里等待食物煮熟,因为这需要时间.所以他离开了订单并继续他的工作,直到订单准备好.现在想象他离开了订单,然后立即检查柜台.看到那里还没有食物,他会非常失望.这正是你在placemark厨师甚至一秒钟做出订单之前立即尝试读取变量时所做的事情.

那么答案是什么?您可以创建另一个创建注释并将其放在地图上的方法.该方法应该将地标作为参数,然后你可以从块中调用该方法(这也是在你真正拥有地标之后.)把这想象成服务员在订单之后想做的所有工作.准备就绪,就像接受客户订单一样.

还有其他方法可以做到这一点.但是对于你在这里展示的一个单一地标,这是一种处理这个问题的简单方法.显然,您还应该添加错误处理,以防您找不到地标,或者服务不可用等.如果查找失败,地标将为零,您可以检查错误以获取更多信息.

希望有所帮助.