等到一个块到达完成块

时间:2014-12-04 16:06:03

标签: ios objective-c-blocks

我想等待异步任务完成(获取反向地理编码结果),所以我使用如下块: 该方法将执行[self.dataArray count]次:

    for (Trip_ObjC *trip in self.dataArray) {

            NSData *tripData = [trip.coordinates dataUsingEncoding:NSUTF8StringEncoding];
            NSArray *coordinatesArray = [NSJSONSerialization JSONObjectWithData:tripData options:NSJSONReadingMutableContainers error:&error];

            [self prepareDistanceAndTimeArray:trip andCoordinates:coordinatesArray];
            [self prepareMapRoutes:trip andCoordinates:coordinatesArray];
            [self prepareDates:trip];

//HERE IS THE TARGETTED METHOD
            NSLog(@"entered");
            [self getAddressFromTrip:trip andCoordinates:coordinatesArray completionHandler:^{
                NSLog(@"GOT ADDRESS");
            }];
        }

然后这是getAddressFromTrip

的声明
-(void)getAddressFromTrip:(Trip_ObjC*)trip andCoordinates:(NSArray*)tripArray completionHandler:(void (^)(void))completionHandler{
    NSLog(@"getAddressFromTrip with ID %d",trip.id_);

    //Got userLocationBegin
   // GOT userLocationEnd


    [self geocodeLocation:userLocationBegin andUserLocationEnd:userLocationEnd andTripId:trip.id_ completionHandler:^{
        if (completionHandler) {
            NSLog(@"completionHandler");
            completionHandler();
        }
    }];
}

现在问题是,它不是简单地输入reverseGeocodeCoordinate块并执行代码,我只是得到了最后一个循环结果:

 -(void)geocodeLocation:(CLLocation*)userLocationBegin andUserLocationEnd:(CLLocation*)userLocationEnd andTripId:(int)tripId completionHandler:(void (^)(void))completionHandler {
        NSLog(@"geocodeLocation with ID %d",tripId);
        CLLocationCoordinate2D c2dBegin=CLLocationCoordinate2DMake(userLocationBegin.coordinate.latitude, userLocationBegin.coordinate.longitude);

        __block NSString *addressBegin;

        NSLog(@"Before entrering geocoding block");
        [[LMGeocoder sharedInstance] reverseGeocodeCoordinate:c2dBegin
                                                      service:kLMGeocoderGoogleService
                                            completionHandler:^(LMAddress *address, NSError *error) {

                                                if (address && !error) {

                                                    NSLog(@"trip.id_ %d",tripId);
                                                    addressBegin=[NSString stringWithFormat:@"%@ ,%@",address.administrativeArea,address.locality];

if(completionHandler){
                                                    completionHandler();
                                                }
                                                }
                                                else {
                                                    NSLog(@"Error reverse: %@", error.description);
                                                }
                                            }];
    }

LOG:

2014-12-04 16:51:09.435 GOTTIZ[18710:2151731] entered
2014-12-04 16:51:09.436 GOTTIZ[18710:2151731] getAddressFromTrip with ID 11
2014-12-04 16:51:09.436 GOTTIZ[18710:2151731] geocodeLocation with ID 11
2014-12-04 16:51:09.436 GOTTIZ[18710:2151731] Before entrering geocoding block
2014-12-04 16:51:09.436 GOTTIZ[18710:2151731] entered
2014-12-04 16:51:09.436 GOTTIZ[18710:2151731] getAddressFromTrip with ID 13
2014-12-04 16:51:09.436 GOTTIZ[18710:2151731] geocodeLocation with ID 13
2014-12-04 16:51:09.437 GOTTIZ[18710:2151731] Before entrering geocoding block
2014-12-04 16:51:09.437 GOTTIZ[18710:2151731] entered
2014-12-04 16:51:09.437 GOTTIZ[18710:2151731] getAddressFromTrip with ID 14
2014-12-04 16:51:09.437 GOTTIZ[18710:2151731] geocodeLocation with ID 14
2014-12-04 16:51:09.438 GOTTIZ[18710:2151731] Before entrering geocoding block
2014-12-04 16:51:09.438 GOTTIZ[18710:2151731] entered
2014-12-04 16:51:09.438 GOTTIZ[18710:2151731] getAddressFromTrip with ID 9
2014-12-04 16:51:09.438 GOTTIZ[18710:2151731] geocodeLocation with ID 9
2014-12-04 16:51:09.438 GOTTIZ[18710:2151731] Before entrering geocoding block
2014-12-04 16:51:09.438 GOTTIZ[18710:2151731] entered
2014-12-04 16:51:09.439 GOTTIZ[18710:2151731] getAddressFromTrip with ID 1
2014-12-04 16:51:09.439 GOTTIZ[18710:2151731] geocodeLocation with ID 1
2014-12-04 16:51:09.439 GOTTIZ[18710:2151731] Before entrering geocoding block
2014-12-04 16:51:09.536 GOTTIZ[18710:2151731] trip.id_ 1
2014-12-04 16:51:09.852 GOTTIZ[18710:2151731] addressBegin
2014-12-04 16:51:09.852 GOTTIZ[18710:2151731] addressEnd
2014-12-04 16:51:09.852 GOTTIZ[18710:2151731] completionHandler
2014-12-04 16:51:09.852 GOTTIZ[18710:2151731] GOT ADDRESS
2014-12-04 16:51:09.862 GOTTIZ[18710:2151731] addressBegin
2014-12-04 16:51:09.862 GOTTIZ[18710:2151731] addressEnd
2014-12-04 16:51:09.862 GOTTIZ[18710:2151731] completionHandler
2014-12-04 16:51:09.862 GOTTIZ[18710:2151731] GOT ADDRESS
2014-12-04 16:51:09.880 GOTTIZ[18710:2151731] addressBegin
2014-12-04 16:51:09.880 GOTTIZ[18710:2151731] addressEnd
2014-12-04 16:51:09.880 GOTTIZ[18710:2151731] completionHandler
2014-12-04 16:51:09.881 GOTTIZ[18710:2151731] GOT ADDRESS
2014-12-04 16:51:09.894 GOTTIZ[18710:2151731] addressBegin
2014-12-04 16:51:09.895 GOTTIZ[18710:2151731] addressEnd
2014-12-04 16:51:09.895 GOTTIZ[18710:2151731] completionHandler
2014-12-04 16:51:09.895 GOTTIZ[18710:2151731] GOT ADDRESS
2014-12-04 16:51:10.023 GOTTIZ[18710:2151731] addressBegin
2014-12-04 16:51:10.023 GOTTIZ[18710:2151731] addressEnd
2014-12-04 16:51:10.023 GOTTIZ[18710:2151731] completionHandler
2014-12-04 16:51:10.023 GOTTIZ[18710:2151731] GOT ADDRESS

您可以注意到它没有进入reverseGeocodeCoordinate块并继续循环直到最后一个元素并显示它。并且trip.id_仅显示一次。 我不知道它实际上是如何继续循环的,即使它没有收到completionHandler()。

1 个答案:

答案 0 :(得分:2)

查看LMGeocoder的代码,它确实设计为一次用于一个请求,因为它使用保持状态的单例模式:

@interface LMGeocoder ()
{
    NSMutableData *receivedData;
    CLLocationCoordinate2D requestedCoordinate;
    NSString *requestedAddress;
    LMGeocodeCallback completionHandler;
    LMGeocoderService currentService;
    BOOL isReverseGeocoding;
}
@end

因此,您无法像现在一样遍历请求,而是需要链接事件;只有在前一个查询完成后才开始下一个查询。

这超出了LMGeocoder包含的Google代码所施加的限制(我没有查看Google代码)。

编辑这是链接请求的意思的一个例子:

  1. 在类实现文件中添加一个将当前索引保存到self.dataArray的实例变量:

    @interface YourClass () {
        NSUInteger _dataArrayIndex;
    }
    - (void)_nextRequest;
    @end
    
  2. 添加执行 next 请求的方法。在首先确保_dataArrayIndex重置为0后,必须调用此方法来启动整个请求链:

    - (void)_nextRequest
    {
        if (_dataArrayIndex >= [self.dataArray count])
            return;
        Trip_ObjC *trip = self.dataArray[_dataArrayIndex++];
        NSData *tripData = [trip.coordinates dataUsingEncoding:NSUTF8StringEncoding];
        NSArray *coordinatesArray = [NSJSONSerialization JSONObjectWithData:tripData options:NSJSONReadingMutableContainers error:&error];
    
        [self prepareDistanceAndTimeArray:trip andCoordinates:coordinatesArray];
        [self prepareMapRoutes:trip andCoordinates:coordinatesArray];
        [self prepareDates:trip];
    
        NSLog(@"entered");
        [self getAddressFromTrip:trip andCoordinates:coordinatesArray completionHandler:^{
            NSLog(@"GOT ADDRESS");
        }];
    }
    
  3. 最后在完成处理程序中,调用_nextRequest来处理下一个请求。这就是链条。