2015-04-29 4 views
0

Я новичок в разработке в iOS. Я искал и пробовал несколько способов, но программа не хочет ждать завершения асинхронного вызова.Цель C - Как дождаться завершения асинхронного вызова

При отладке функция CheckForHost сначала возвращает -1 как retVal. Это приводит к тому, что метод вызывает функцию. Через секунду программа вернется в функцию CheckForHost, установив правильное значение в retVal. Я также пытался с NSCondition, но не повезло ...

Может кто-нибудь сказать мне, что я делаю неправильно или должен поступить иначе? Большое спасибо за вашу помощь!

Код ниже:

-(int)CheckForHost 
 
{ 
 
    InternetActive = -1; 
 
    HostActive = -1; 
 
    dispatch_queue_t myQueue = dispatch_queue_create("my queue", NULL); 
 
    __block int retVal = -1; 
 
    dispatch_async(myQueue, ^{ 
 
     [self HostInit]; 
 
     dispatch_async(dispatch_get_main_queue(), ^{ 
 
      [internetReachable stopNotifier]; 
 
      [hostReachable stopNotifier]; 
 
      [[NSNotificationCenter defaultCenter] removeObserver:self]; 
 
      if (InternetActive == 0) { 
 
       retVal = 0; 
 
      } else if (HostActive == 0) { 
 
       retVal = 1; 
 
      } else 
 
       retVal = 2; 
 
     }); 
 
    }); 
 
    return retVal; 
 
} 
 

 
-(void)HostInit 
 
{ 
 
    // check for internet connection 
 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil]; 
 
    internetReachable = [Reachability reachabilityForInternetConnection]; 
 
    [internetReachable startNotifier]; 
 
    // check if a pathway to a random host exists 
 
    hostReachable = [Reachability reachabilityWithHostName:@"www.apple.com"]; 
 
    [hostReachable startNotifier]; 
 
    // now patiently wait for the notification 
 
} 
 

 
-(void)checkNetworkStatus:(NSNotification *)notice 
 
{ 
 
    // called after network status changes 
 
    NetworkStatus internetStatus = [internetReachable currentReachabilityStatus]; 
 
    switch (internetStatus) 
 
    { 
 
     case NotReachable: 
 
     { 
 
      NSLog(@"The internet is down."); 
 
      InternetActive = 0; 
 
      break; 
 
     } 
 
     case ReachableViaWiFi: 
 
     { 
 
      NSLog(@"The internet is working via WIFI."); 
 
      InternetActive = 1; 
 
      break; 
 
     } 
 
     case ReachableViaWWAN: 
 
     { 
 
      NSLog(@"The internet is working via WWAN."); 
 
      InternetActive = 1; 
 
      break; 
 
     } 
 
    } 
 
    NetworkStatus hostStatus = [hostReachable currentReachabilityStatus]; 
 
    switch (hostStatus) 
 
    { 
 
     case NotReachable: 
 
     { 
 
      NSLog(@"A gateway to the host server is down."); 
 
      HostActive = 0; 
 
      break; 
 
     } 
 
     case ReachableViaWiFi: 
 
     { 
 
      NSLog(@"A gateway to the host server is working via WIFI."); 
 
      HostActive = 1; 
 
      break; 
 
     } 
 
     case ReachableViaWWAN: 
 
     { 
 
      NSLog(@"A gateway to the host server is working via WWAN."); 
 
      HostActive = 1; 
 
      break; 
 
     } 
 
    } 
 
}

+1

С каким потолком вы звоните? Вы никогда не должны ждать в потоке пользовательского интерфейса. Используйте обработчик завершения. –

ответ

0

Я хотел бы использовать блоки, они легко и надежно

Вот пример функция с блоком:

- (void)checkForHostWithBlock:(void (^)(int myReturnedInt))completion{ 

//Our function does stuff here, i'll copy paste some of your code 

InternetActive = -1; 
    HostActive = -1; 
    dispatch_queue_t myQueue = dispatch_queue_create("my queue", NULL); 
    __block int retVal = -1; 
    dispatch_async(myQueue, ^{ 
     [self HostInit]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [internetReachable stopNotifier]; 
      [hostReachable stopNotifier]; 
      [[NSNotificationCenter defaultCenter] removeObserver:self]; 
      if (InternetActive == 0) { 
       retVal = 0; 
      } else if (HostActive == 0) { 
       retVal = 1; 
      } else 
       retVal = 2; 
      if (completion){ 
       completion(retVal); 
      } 
     }); 
    }); 
} 

Там вы идете.

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

[self checkForHostWithBlock:^(int myReturnInt){ 
    //Executed code when the block is called in checkForHost: 
    NSLog(@"Here is my int : %i !!", myReturnInt); 
}]; 

Обратите внимание, что параметр блока может быть равен нулю, но вы должны убедиться, что вы проверите его в своем методе.

+0

Большое спасибо за пример. Это сработало!!! –

+0

Убедитесь, что вы понимаете, как это работает, и не просто скопируйте его! Но в любом случае, пожалуйста! –

0

Ну, если вы хотите ждать завершения выполнения, вы не должны выполнять его асинхронно. Это смысл асинхронности, чтобы не ждать.

Итак, если вы хотите подождать, выполните блок синхронно или используйте semaphore. (Я не сказал, что это хорошая идея, чтобы выполнить синхронно. Я просто сказал, что делать.)

+0

Благодарим вас за ввод. Я изменил в CheckForHost от dispatch_async до dispatch_sync оба экземпляра. В этом случае я никогда не получаю возврата вообще. Изменение второго экземпляра в этой функции dispatch_async дает мне тот же результат, что и в моем вопросе. Поскольку я новичок в iOS, не могли бы вы рассказать мне, что исправить в коде выше? Благодарю. –

+0

Ну, если вы хотите, чтобы он был синхронизирован, просто не используйте блоки, но пишите код по строкам. Однако, как я сказал в своем A, это лучший подход, чтобы сохранить его асинхронно и предоставить блоку обработчик завершения. Но это приводит к основному объяснению GCD. Документы для этого лучше. –

+0

Будьте осторожны при синхронном выполнении кода, он заморозит все, что работает на стороне, пока этот код запущен. Я думаю, мы можем с уверенностью сказать, что вы обычно (в 99% случаев) предпочли бы, чтобы ваш код выполнялся асинхронно –

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