2014-12-04 2 views
0

Я хочу ждать задача асинхронной закончить (получение обратный результат геокодирования), поэтому я использую блоки, как следующим образом: метод будет выполняться [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_ отображается только один раз. Я не знаю, как он на самом деле продолжает цикл, даже если он не получает completeHandler().

+0

просто хотел заметить, что если вы сделаете так много запросов сразу, Google заблокирует вас довольно быстро. – Daniel

+0

@simpleBob: Итак, каков наилучший подход к обратному геокодированию? Спасибо . – androniennn

+1

используйте кеширование, сохраните все уже сделанные запросы и попытайтесь отправить как можно меньше запросов. – Daniel

ответ

2

Глядя на код LMGeocoder, это, безусловно, предназначен для использования в течение одного запроса в то время, учитывая, что использует шаблон одноэлементный, который держит состояние:

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

Поэтому вы не можете перебрать запросов, как вы делают, но вместо этого вам понадобится цепь события; начиная следующий запрос только после завершения предыдущего.

Это не соответствует ограничениям, налагаемым кодом Google, который LMGeocoder обертывает (я не смотрел код Google).

EDIT Это пример того, что я имею в виду, приковав запросы:

  1. Добавить переменную экземпляра, который содержит текущий индекс в self.dataArray в файле реализации класса:

    @interface YourClass() { 
        NSUInteger _dataArrayIndex; 
    } 
    - (void)_nextRequest; 
    @end 
    
  2. Добавьте метод, который выполняет запрос следующего. Это должно быть названо, чтобы начать всю цепочку запроса, после первого обеспечения, что _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 для обработки следующего запроса. Это цепочка.

+0

О да! У вас есть основания ! Но есть ли у вас представление о наилучшем подходе к геокодированию? Я боюсь, что, если я сделаю много запросов (в Google или Apple обратно с помощью геокодирования), они заблокируют меня. – androniennn

+0

@androniennn Я не знаю, как заблокирован Google/Apple, и это выходит за рамки вопроса. Как уже упоминалось в моем ответе, вам нужно связать запросы, чтобы 1) сохранить текущий индекс в массиве в переменной экземпляра. 2) поместите код из этого цикла в метод, который запускает запрос, как он это делает в настоящее время. 3) вызов этого метода из обработчика завершения. – Droppy

+1

@ androniennn: Apple не будет блокировать вас; API Google ограничит вас, хотя вы можете подать заявку на увеличение лимита. – shim

Смежные вопросы