Frage

10Ich habe ein paar Beiträge auf SOF zu asynchronen Aufrufen mit GCD verfolgt und das funktioniert gut, WENN die Antwort des Remote-Servers schnell genug ist, wie beim Arbeiten und Testen mit einem lokalen Testserver.

Versuchte SOF-Lösungen:

Warten, bis zwei asynchrone Blöcke ausgeführt wurden, bevor ein weiterer Block gestartet wird

iPhone – Hauptthread von Grand Central Dispatch

Nachdem ich nun einen Remote-Server eingerichtet habe, dauert es mindestens 8 Sekunden, bis er seine JSON-Daten zurückgibt, und der GCD-Code verhält sich so, als würde er nicht auf den Abschluss des asynchronen Aufrufs warten, bevor er die Benutzeroberfläche aktualisiert, und am Ende erhalte ich eine Tabellenansicht das ist leer.

Die einzige Möglichkeit, dass sich das richtig verhält, besteht darin, in der Zeile zu bleiben

[NSThread sleepForTimeInterval:10.0];

Dies zwingt die App, 10 Sekunden zu warten und ermöglicht [self -runirestRequest: Requesturl]; Um mit Daten zurückzukehren, erhalte ich Daten zurück.Dies ist offensichtlich ein Hack und ich möchte, dass mein GCD-Code ordnungsgemäß funktioniert.

Gibt es eine Möglichkeit, den UI-Code erst dann auszuführen, wenn der asynchrone Aufruf mit Daten zurückgegeben wurde?

Notiz:Die von runUnirestRequest zurückgegebenen Daten liegen im JSON-Format vor, werden deserialisiert und in einer Instanz von „salesData“ platziert.

Mein Code für GCD-Aufrufe lautet wie folgt:

- (void)viewDidLoad
{
...unrelated code...

[self createActivityIndicator];

dispatch_queue_t jsonQueue = dispatch_queue_create("com.ppos.pbsdashboard", NULL);

//  Start block on background queue so the main thread is not frozen
//  which prevents apps UI freeze
[activityIndicator startAnimating];

dispatch_async(jsonQueue, ^{

    // Run remote RESTful request
    [self runUnirestRequest:requestUrl];

    // Force main thread to wait a bit to allow ansync dispatch
    // to get its response with data
    [NSThread sleepForTimeInterval:10.0];

    // Everything in background thread is done.
    // Call another block on main thread to do UI stuff
    dispatch_sync(dispatch_get_main_queue(), ^{

        // Back within main thread
        [activityIndicator stopAnimating];

        PBSVCDataDisplay *dataVc = [[PBSVCDataDisplay alloc] init];

        [dataVc setSalesData:salesData];

        [self performSegueWithIdentifier:@"showDataChart" sender:self];
    });
});
}

runUnirestRequest-Funktion

- (void) runUnirestRequest:(NSString*)urlToSendRequestTo
{
[requestVCMessages setTextAlignment:NSTextAlignmentCenter];
[requestVCMessages setText:@"Processing request"];

// Handle errors if any occur and display a friendly user message.
@try{

    NSDictionary* headers = @{@"p": settingsPassPhrase};

    [[UNIRest get:^(UNISimpleRequest* request) {
        [request setUrl:urlToSendRequestTo];
        [request setHeaders:headers];
    }] asJsonAsync:^(UNIHTTPJsonResponse* response, NSError *error) {

        UNIJsonNode *jsonNde = [response body];

        NSDictionary *jsonAsDictionary = jsonNde.JSONObject;

        salesData = [self deserializeJsonPacket:(NSDictionary*)jsonAsDictionary withCalenderType:[requestParameters calendType]];
    }];


}
@catch(NSException *exception){
    [requestVCMessages setTextAlignment:NSTextAlignmentLeft];
    NSString *errHeader = @"An error has occured.\n\n";
    NSString *errName = [exception name];
    NSString *errString = nil;

    // Compare the error name so we can customize the outout error message
    if([errName isEqualToString:@"NSInvalidArgumentException"]){
        errString = [errHeader stringByAppendingString:@"The reason for the error is probably because data for an invalid date has been requested."];
    }else{
        errString = [errHeader stringByAppendingString:@"General exception. Please check that your server is responding or that you have requested data for a valid date."];
    }
    salesData = nil;
    [requestVCMessages setText:errString];
}
}
War es hilfreich?

Lösung

So verwenden Sie asynchrone Anrufe.Was Sie hier tun, ist ein asynchroner Anruf und synchron.

Ihr asynchroner Code sollte sich nicht darauf achten, wenn der Anruf 10 ms, 10 Sekunden oder 10 Minuten dauert.Es sollte für alle Fälle arbeiten.

Vielleicht solltest du es so etwas einrichten wie ...

generasacodicetagpre.

Sie scheinen den bereits asynchronen Anruf auf der JSON-Anforderung in einem anderen Async-Block zu verpacken.

nutzen Sie einfach die Tatsache, dass die Anfrage bereits asynchron ist.

Andere Tipps

Weil du runUnirestRequest ist aync.Und Sie rufen es bei a auf dispatch_async Stellungnahme. [self runUnirestRequest:requestUrl] Die Ausführung wird nicht warten bis runUnirestRequest erledigt.Du solltest dich ändern runUnirestRequest stattdessen synchronisieren.Dies könnte Ihr Problem beheben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top