2013-08-02 3 views
7

ich die folgende Testklasse gemacht zu versuchen, Daten aus Parse Abrufen:findObjectsInBackgroundWithBlock: erhält Daten von Parse, aber Daten existieren nur innerhalb des Blockes

-(void)retrieveDataFromParse 
{ 
    PFQuery *query = [PFQuery queryWithClassName:@"TestObject"]; 

    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { 
     if(!error){ 
      for (PFObject *object in objects){ 
       NSString *nameFromObject = [NSString stringWithFormat:@"%@", [object objectForKey:@"Name"]]; 
       NSString *dateFromObject = [NSString stringWithFormat:@"%@", [object createdAt]]; 
       NSString *scoreFromObject = [NSString stringWithFormat:@"%@", [object objectForKey:@"Score"]]; 
       [self addNewScore:scoreFromObject andDate:dateFromObject forUserName:nameFromObject]; 
       NSLog(@"The dictionary is %@", self.scoreDictionary); //<-- here it works printing out the whole dictionary 
      } 
     } else { 
      NSLog(@"Error: %@ %@", error, [error userInfo]); 
     } 
    }]; 
    NSLog(@"The dictionary is %@", self.scoreDictionary); //<- but after the block is called, here the dictionary is again empty... 
} 

Per kommentierten Abschnitt in dem Code, wenn ich self.scoreDictionary drucken Innerhalb des Codes funktioniert es gut und ich sehe mein ganzes Wörterbuch, wenn es schrittweise gefüllt wird. Nachdem der Block jedoch beendet ist, wenn ich das Wörterbuch erneut drucke, ist es jetzt leer. Ich habe das mit den API-Dokumenten überprüft, bin aber immer noch unsicher, was ich falsch mache.

Antwort

13

Die letzte Anweisung NSLog(@"The dictionary is %@", self.scoreDictionary) wird nach Abschluss des Blocks nicht ausgeführt. Es wird ausgeführt, nachdem die findObjectsInBackgroundWithBlock Methode zurückgibt. findObjectsInBackgroundWithBlock führt vermutlich etwas in einem separaten Thread aus, und Ihr Block wird möglicherweise tatsächlich erst einige Zeit nach der letzten NSLog-Anweisung ausgeführt. Grafisch geschieht so etwas wie dies wahrscheinlich:

Thread 1 
-------- 
retriveDataFromParse called 
invoke findObjectsInBackgroundWithBlock 
findObjectsInBackgroundWithBlock queues up work on another thread 
findObjectsInBackgroundWithBlock returns immediately  | 
NSLog statement - self.scoreDictionary not yet updated | 
retriveDataFromParse returns        | 
.               V 
.      Thread 2, starting X milliseconds later 
.      -------- 
.      findObjectsInBackgroundWithBlock does some work 
.      your block is called 
.      for-loop in your block 
.      Now self.scoreDictionary has some data 
.      NSLog statement inside your block 

Sie wahrscheinlich wollen, darüber nachzudenken, was wollen Sie mit Ihrem scoreDictionary Daten zu tun, nachdem Sie abgerufen haben es? Möchten Sie beispielsweise die Benutzeroberfläche aktualisieren, eine andere Methode aufrufen usw.? Sie werden dies innerhalb Ihres Blocks tun, an welchem ​​Punkt Sie wissen, dass die Daten erfolgreich abgerufen wurden. wenn Sie eine Tabellenansicht musste man neu zu laden möchten, können Sie dies zum Beispiel tun:

for (PFObject *object in objects){ 
    .... 
} 
dispatch_async(dispatch_get_main_queue(), ^{ 
    [self updateMyUserInterfaceOrSomething]; 
}); 

Notiere die dispatch_async - wenn die Arbeit, die Sie nach der Aktualisierung Ihrer Daten tun müssen, beinhaltet die Benutzeroberfläche zu ändern, werden Sie wollen das auf dem Hauptthread auszuführen.

+0

Dank, vor allem für die sehr hilfreich Darstellung, die die Fäden zu zeigen! – daspianist

Verwandte Themen