2012-09-03 5 views
5

Innerhalb der folgenden Funktion habe ich einen Block verwendet. Aber wenn ich diese Funktion aufrufe, wird sie zurückgegeben, noch bevor der Block ausgeführt wird. Ich verstehe, dass Block inturn die Threads verwendet und separat ausführt, so dass die Funktion nicht darauf wartet, dass sie zurückkehrt. Aber, gibt es eine andere Möglichkeit, die Funktionsausführung warten zu lassen, oder eine andere Möglichkeit, um die Funktionalität dieses Blocks zu erreichen, ohne den Block selbst zu benutzen?Wie mache ich einen Funktionsaufruf in IOS zu warten, bis der Block in dieser Funktion vollständig ausgeführt wird?

-(int)findCurrentZip 
{ 
     CLLocation *userLocation = [[CLLocation alloc] initWithLatitude:[self findCurrentLatitude] 
                   longitude:[self findCurrentLongitude]]; 
     int zipcode; 
     self.myGeocoder = [[CLGeocoder alloc] init]; 
     [self.myGeocoder 
     reverseGeocodeLocation:userLocation 
     completionHandler: (id)^(NSArray *placemarks, NSError *error) { 
      if (error == nil && [placemarks count] > 0) 
      { 
       NSLog(@"Placemarks: %@",placemarks); 
       CLPlacemark *placemark = [placemarks objectAtIndex:0]; 
       NSLog(@"Country = %@", placemark.country); 
       NSLog(@"Postal Code = %@", placemark.postalCode); 
       zipcode = (int)placemark.postalCode; 
       NSLog(@"Locality = %@", placemark.locality); 
       NSLog(@"Country%@",[placemarks lastObject]); 
      } 
      else if (error == nil && [placemarks count] == 0) 
      { 
       NSLog(@"No results were returned."); 
      } 
      else if (error != nil) 
      { 

      } 
     }]; 

     return zipcode; 
    } 
+0

nur als Notiz. Es gibt einen Grund, dass postalCode ein NSString in CLPlacemark ist. Postleitzahlen können mit einer 0 beginnen! –

+2

oh, und '(int) placemark.postalCode' konvertiert diesen NSString nicht in einen int ;-) –

Antwort

8

Zuerst würde ich vorschlagen, Ihr Design zu überdenken. Anstatt den zipCode-Wert von dieser Methode zurückzugeben, rufen Sie eine andere Methode im completionHandler auf (erstellen Sie ein Protokoll/Delegate oder was auch immer). Die Methode reverseGeocodeLocation:: kann einige Zeit in Anspruch nehmen, und Sie möchten die Ausführung des auf das Ergebnis wartenden Hauptthreads nicht pausieren.

Wenn Sie jedoch blockieren möchten, könnten Sie (missbrauchen?) Eine dispatch_semaphore_t verwenden. Initialisieren Sie es auf 0 und dispatch_semaphore_wait nach dem Anruf zu reverseGeocodeLocation::. In der Completion-Handler-Signal mit dispatch_semaphore_signal.

Weitere Informationen: Using Dispatch Semaphores to Regulate the Use of Finite Resources

edit: und wie andere vorgeschlagen, erklären zipCode mit einem __block Qualifier

+0

Benutze auch kein 'wartendes' Muster, denn wenn du' findCurrentZip' aus dem Hauptthread herausrufst, ist deine App zufällig bleib stecken, bis du die Postleitzahl findest. Schlechtes Design ... – robertvojta

+0

Ja, scheint Protokoll/Delegat ist die optimierte und richtige Technik für dieses Szenario .. –