Ich bin neu in Objective C und iOS Entwicklung im Allgemeinen. Ich versuche, eine App zu erstellen, die eine HTTP-Anfrage machen und den Inhalt auf einem Etikett anzeigen würde.Warte, bis NSURLSessionDataTask zurückkommt
Als ich zu testen begann, bemerkte ich, dass das Etikett leer war, obwohl meine Logs zeigten, dass ich Daten zurück hatte. Scheinbar passiert dies, weil die Antwort nicht bereit ist, wenn der Etikettentext aktualisiert wird.
Ich habe eine Schleife auf die Oberseite, um das zu beheben, aber ich bin mir fast sicher, dass es eine bessere Möglichkeit geben muss, damit umzugehen.
ViewController.m
- (IBAction)buttonSearch:(id)sender {
HttpRequest *http = [[HttpRequest alloc] init];
[http sendRequestFromURL: @"https://en.wiktionary.org/wiki/incredible"];
//I put this here to give some time for the url session to comeback.
int count;
while (http.responseText ==nil) {
self.outputLabel.text = [NSString stringWithFormat: @"Getting data %i ", count];
}
self.outputLabel.text = http.responseText;
}
HttpRequest.h
#import <Foundation/Foundation.h>
@interface HttpRequest : NSObject
@property (strong, nonatomic) NSString *responseText;
- (void) sendRequestFromURL: (NSString *) url;
- (NSString *) getElementBetweenText: (NSString *) start andText: (NSString *) end;
@end
HttpRequest.m
@implementation HttpRequest
- (void) sendRequestFromURL: (NSString *) url {
NSURL *myURL = [NSURL URLWithString: url];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: myURL];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest: request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
self.responseText = [[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding];
}];
[task resume];
}
Vielen Dank für die Hilfe :)
aktualisiert
hier viel für die sehr nützlichen Kommentare Nach der Lektüre wurde mir klar, dass ich den ganzen Punkt fehlte. Technisch gesehen wird NSURLSessionDataTask einen Task zu einer Warteschlange hinzufügen, die den Aufruf asynchron durchführt, und dann muss ich diesen Aufruf mit einem Codeblock versehen, den ich ausführen möchte, wenn der von der Task erzeugte Thread abgeschlossen wurde.
Duncan bedankt sich sehr für die Antwort und die Kommentare im Code. Das hat mir sehr geholfen zu verstehen.
Also schrieb ich meine Prozeduren mit den bereitgestellten Informationen um. Beachten Sie, dass sie ein wenig wortreich sind, aber ich wollte, dass es das ganze Konzept für jetzt versteht. (Erkläre ich einen Codeblock, anstatt sie nisten)
HttpRequest.m
- (void) sendRequestFromURL: (NSString *) url
completion:(void (^)(NSString *, NSError *))completionBlock {
NSURL *myURL = [NSURL URLWithString: url];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: myURL];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest: request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//Create a block to handle the background thread in the dispatch method.
void (^runAfterCompletion)(void) = ^void (void) {
if (error) {
completionBlock (nil, error);
} else {
NSString *dataText = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
completionBlock(dataText, error);
}
};
//Dispatch the queue
dispatch_async(dispatch_get_main_queue(), runAfterCompletion);
}];
[task resume];
}
ViewController.m
- (IBAction)buttonSearch:(id)sender {
NSString *const myURL = @"https://en.wiktionary.org/wiki/incredible";
HttpRequest *http = [[HttpRequest alloc] init];
[http sendRequestFromURL: myURL
completion: ^(NSString *str, NSError *error) {
if (error) {
self.outputText.text = [error localizedDescription];
} else {
self.outputText.text = str;
}
}];
}
Bitte zögern Sie nicht auf meinem neuen Code zu kommentieren. Stil, falsche Verwendung, falscher Fluss; Feedback ist sehr wichtig in dieser Phase des Lernens, so kann ich ein besserer Entwickler werden :)
Nochmals vielen Dank für die Antworten.
Sie sollten einen Completion-Handler-Block die gleiche verwenden Sie eine in der "DataTaskWithRequest" -Aufruf. Fügen Sie den Parametern von 'sendRequestFromURL' einen Block als Abschlussblock hinzu, und rufen Sie diesen Block auf, wenn die Anfrage beendet wurde. In den Block schreiben Sie Ihren Code für die Aktualisierung der Bezeichnung – luk2302